@creeperhost/modlens-mcp 1.6.18 → 1.6.20
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 +112 -15
- package/TESTING.md +69 -0
- package/dist/cli.js +49 -13
- package/dist/cli.js.map +1 -1
- package/dist/curseforge.d.ts +9 -7
- package/dist/curseforge.d.ts.map +1 -1
- package/dist/curseforge.js +48 -55
- package/dist/curseforge.js.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +31 -1
- package/dist/db.js.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +1 -0
- package/dist/embeddings.js.map +1 -1
- package/dist/feed-the-beast.d.ts +5 -5
- package/dist/feed-the-beast.d.ts.map +1 -1
- package/dist/feed-the-beast.js +5 -21
- package/dist/feed-the-beast.js.map +1 -1
- package/dist/java-tools.d.ts +1 -0
- package/dist/java-tools.d.ts.map +1 -1
- package/dist/java-tools.js +31 -7
- package/dist/java-tools.js.map +1 -1
- package/dist/launcher.js +15 -0
- package/dist/launcher.js.map +1 -1
- package/dist/mappings.d.ts +4 -1
- package/dist/mappings.d.ts.map +1 -1
- package/dist/mappings.js +120 -52
- package/dist/mappings.js.map +1 -1
- package/dist/minecraft.d.ts +0 -4
- package/dist/minecraft.d.ts.map +1 -1
- package/dist/minecraft.js +7 -23
- package/dist/minecraft.js.map +1 -1
- package/dist/mod-artifacts.d.ts +4 -0
- package/dist/mod-artifacts.d.ts.map +1 -0
- package/dist/mod-artifacts.js +58 -0
- package/dist/mod-artifacts.js.map +1 -0
- package/dist/modpacks-ch.d.ts +72 -46
- package/dist/modpacks-ch.d.ts.map +1 -1
- package/dist/modpacks-ch.js +134 -20
- package/dist/modpacks-ch.js.map +1 -1
- package/dist/modrinth.d.ts +14 -6
- package/dist/modrinth.d.ts.map +1 -1
- package/dist/modrinth.js +70 -55
- package/dist/modrinth.js.map +1 -1
- package/dist/platform-adapter.d.ts +1 -0
- package/dist/platform-adapter.d.ts.map +1 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +20 -44
- package/dist/platform.js.map +1 -1
- package/dist/primer-catalog.d.ts +15 -0
- package/dist/primer-catalog.d.ts.map +1 -0
- package/dist/primer-catalog.js +43 -0
- package/dist/primer-catalog.js.map +1 -0
- package/dist/primer-content.d.ts +7 -0
- package/dist/primer-content.d.ts.map +1 -0
- package/dist/primer-content.js +185 -0
- package/dist/primer-content.js.map +1 -0
- package/dist/processor.d.ts +5 -0
- package/dist/processor.d.ts.map +1 -1
- package/dist/processor.js +166 -46
- package/dist/processor.js.map +1 -1
- package/dist/registry-submission.d.ts +34 -0
- package/dist/registry-submission.d.ts.map +1 -0
- package/dist/registry-submission.js +128 -0
- package/dist/registry-submission.js.map +1 -0
- package/dist/repositories/array-fields.d.ts +3 -0
- package/dist/repositories/array-fields.d.ts.map +1 -0
- package/dist/repositories/array-fields.js +8 -0
- package/dist/repositories/array-fields.js.map +1 -0
- package/dist/repositories/embeddings-sqlite.d.ts +1 -0
- package/dist/repositories/embeddings-sqlite.d.ts.map +1 -1
- package/dist/repositories/embeddings-sqlite.js +26 -58
- package/dist/repositories/embeddings-sqlite.js.map +1 -1
- package/dist/repositories/embeddings.d.ts.map +1 -1
- package/dist/repositories/embeddings.js +26 -3
- package/dist/repositories/embeddings.js.map +1 -1
- package/dist/repositories/index.d.ts +1 -1
- package/dist/repositories/index.d.ts.map +1 -1
- package/dist/repositories/mod.d.ts +8 -5
- package/dist/repositories/mod.d.ts.map +1 -1
- package/dist/repositories/mod.js +25 -11
- package/dist/repositories/mod.js.map +1 -1
- package/dist/repositories/packs.d.ts.map +1 -1
- package/dist/repositories/packs.js +10 -2
- package/dist/repositories/packs.js.map +1 -1
- package/dist/search-adapter.d.ts +2 -0
- package/dist/search-adapter.d.ts.map +1 -1
- package/dist/search-adapter.js +21 -9
- package/dist/search-adapter.js.map +1 -1
- package/dist/security.d.ts +2 -0
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +5 -1
- package/dist/security.js.map +1 -1
- package/dist/server.js +80 -35
- package/dist/server.js.map +1 -1
- package/dist/setup.js +9 -4
- package/dist/setup.js.map +1 -1
- package/dist/sqlite-json.d.ts +3 -0
- package/dist/sqlite-json.d.ts.map +1 -0
- package/dist/sqlite-json.js +78 -0
- package/dist/sqlite-json.js.map +1 -0
- package/dist/sqlite-parameters.d.ts +3 -0
- package/dist/sqlite-parameters.d.ts.map +1 -0
- package/dist/sqlite-parameters.js +19 -0
- package/dist/sqlite-parameters.js.map +1 -0
- package/dist/sqlite-schema.d.ts +4 -0
- package/dist/sqlite-schema.d.ts.map +1 -0
- package/dist/sqlite-schema.js +76 -0
- package/dist/sqlite-schema.js.map +1 -0
- package/dist/tools/catalog.d.ts +1 -6
- package/dist/tools/catalog.d.ts.map +1 -1
- package/dist/tools/catalog.js +10 -14
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/compat-check.d.ts.map +1 -1
- package/dist/tools/compat-check.js +18 -30
- package/dist/tools/compat-check.js.map +1 -1
- package/dist/tools/diagnostics.js.map +1 -1
- package/dist/tools/docs.d.ts.map +1 -1
- package/dist/tools/docs.js +8 -3
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/embed-registry.d.ts +20 -4
- package/dist/tools/embed-registry.d.ts.map +1 -1
- package/dist/tools/embed-registry.js +30 -19
- package/dist/tools/embed-registry.js.map +1 -1
- package/dist/tools/graphify.d.ts +19 -4
- package/dist/tools/graphify.d.ts.map +1 -1
- package/dist/tools/graphify.js +61 -13
- package/dist/tools/graphify.js.map +1 -1
- package/dist/tools/ingest.d.ts.map +1 -1
- package/dist/tools/ingest.js +4 -4
- package/dist/tools/ingest.js.map +1 -1
- package/dist/tools/kubejs.js +1 -1
- package/dist/tools/kubejs.js.map +1 -1
- package/dist/tools/mc-fts.d.ts.map +1 -1
- package/dist/tools/mc-fts.js +9 -4
- package/dist/tools/mc-fts.js.map +1 -1
- package/dist/tools/mcmeta.d.ts +10 -1
- package/dist/tools/mcmeta.d.ts.map +1 -1
- package/dist/tools/mcmeta.js +43 -29
- package/dist/tools/mcmeta.js.map +1 -1
- package/dist/tools/mixin-scan.d.ts +12 -6
- package/dist/tools/mixin-scan.d.ts.map +1 -1
- package/dist/tools/mixin-scan.js +12 -7
- package/dist/tools/mixin-scan.js.map +1 -1
- package/dist/tools/mod-data.d.ts.map +1 -1
- package/dist/tools/mod-data.js +40 -27
- package/dist/tools/mod-data.js.map +1 -1
- package/dist/tools/modpacks-ch.d.ts +9 -5
- package/dist/tools/modpacks-ch.d.ts.map +1 -1
- package/dist/tools/modpacks-ch.js +54 -33
- package/dist/tools/modpacks-ch.js.map +1 -1
- package/dist/tools/packtools.js +3 -3
- package/dist/tools/packtools.js.map +1 -1
- package/dist/tools/platform.d.ts +2 -2
- package/dist/tools/platform.d.ts.map +1 -1
- package/dist/tools/platform.js +33 -23
- package/dist/tools/platform.js.map +1 -1
- package/dist/tools/primers.d.ts +133 -22
- package/dist/tools/primers.d.ts.map +1 -1
- package/dist/tools/primers.js +391 -386
- package/dist/tools/primers.js.map +1 -1
- package/dist/tools/project.d.ts +342 -0
- package/dist/tools/project.d.ts.map +1 -0
- package/dist/tools/project.js +519 -0
- package/dist/tools/project.js.map +1 -0
- package/dist/tools/reports.d.ts.map +1 -1
- package/dist/tools/reports.js +5 -3
- package/dist/tools/reports.js.map +1 -1
- package/dist/tools/vanilla-data.d.ts.map +1 -1
- package/dist/tools/vanilla-data.js +3 -33
- package/dist/tools/vanilla-data.js.map +1 -1
- package/dist/tools/vanilla.d.ts +3 -1
- package/dist/tools/vanilla.d.ts.map +1 -1
- package/dist/tools/vanilla.js +26 -12
- package/dist/tools/vanilla.js.map +1 -1
- package/dist/tools/version-diff.d.ts.map +1 -1
- package/dist/tools/version-diff.js +4 -24
- package/dist/tools/version-diff.js.map +1 -1
- package/dist/version-ranges.d.ts +5 -0
- package/dist/version-ranges.d.ts.map +1 -0
- package/dist/version-ranges.js +93 -0
- package/dist/version-ranges.js.map +1 -0
- package/package.json +9 -1
- package/prisma/backends/template.db +0 -0
- package/scripts/build-template-db.mjs +3 -1
- package/scripts/enable-sqlite-vec.mjs +2 -106
- package/scripts/gradle/modlens.init.gradle +154 -0
- package/scripts/project-upload.mjs +74 -0
- package/scripts/test-minecraft-eras.mjs +202 -0
- package/scripts/test-package.mjs +105 -5
- package/scripts/test-primers-live.mjs +93 -0
- package/scripts/test-project-gradle.mjs +76 -0
- package/scripts/test-project-http.mjs +98 -0
- package/scripts/test-setup.mjs +18 -0
package/README.md
CHANGED
|
@@ -49,6 +49,80 @@ npm run start # start the server
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
+
## Gradle project environments
|
|
53
|
+
|
|
54
|
+
ModLens can import the **actual compile classpath** of a Gradle project. The ModDevGradle adapter also exports the matching prepared Minecraft sources and hashes of the AT files used by its artifact task. This lets the AI see project-specific access changes, loader patches and mapped names.
|
|
55
|
+
|
|
56
|
+
Imports are private, immutable snapshots, separate from the shared vanilla/mod caches and database. Re-export and import after changing ATs, dependencies or mappings. The returned `environmentId` selects the new snapshot; earlier IDs still describe their original inputs. This is compile-time context, not a simulation of runtime mixins/coremods.
|
|
57
|
+
|
|
58
|
+
### Export from Gradle
|
|
59
|
+
|
|
60
|
+
In a checkout, run your mod project's wrapper with the supplied init script:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
./gradlew -I /path/to/modlens-mcp/scripts/gradle/modlens.init.gradle :modlensExport
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For an installed package, locate its script first:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx @creeperhost/modlens-mcp --gradle-init-script
|
|
70
|
+
# Pass the printed path to your project's ./gradlew -I command.
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
On Windows, use `gradlew.bat -I "H:\Git\modlens-mcp\scripts\gradle\modlens.init.gradle" :modlensExport`.
|
|
74
|
+
|
|
75
|
+
The task produces `build/modlens/main/environment.zip` and creates a persistent private key at `.gradle/modlens/project-key.txt` in the selected project. The key is not included in the bundle or printed. Keep it out of source control and share it only with clients that should access this project.
|
|
76
|
+
|
|
77
|
+
Use `:subproject:modlensExport` for a module, and `-PmodlensSourceSet=client` to select a different source set. The task runs the classpath's prerequisite tasks, including Minecraft artifact preparation, without launching the game. Referenced project/source-set outputs may need compilation. It does not support Gradle's configuration cache; use `--no-configuration-cache` if necessary.
|
|
78
|
+
|
|
79
|
+
Supported adapter: **ModDevGradle 2.x**, exercised with 2.0.141 / NeoForge 21.1.209 / Minecraft 1.21.1 and Gradle 8.14. Other Java projects can export their resolved compile classpath, including directory dependencies. Automatic source discovery for ForgeGradle/NeoGradle/Loom is not implemented; absent supplied sources, individual classes are decompiled from the exported binaries on demand. Do not interpret generic exports as proof that runtime-only transformations have been applied.
|
|
80
|
+
|
|
81
|
+
Optional metadata overrides: `-PmodlensMinecraftVersion=...`, `-PmodlensMappings=...`. The exporter also reads the common `minecraft_version`, `neo_version` and `forge_version` properties. It exports artifact names/content hashes and selected version metadata, not the project's entire Gradle configuration, repository credentials or absolute dependency paths.
|
|
82
|
+
|
|
83
|
+
### Import locally or remotely
|
|
84
|
+
|
|
85
|
+
Local import and query examples:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx @creeperhost/modlens-mcp --project import-local build/modlens/main/environment.zip --key-file=.gradle/modlens/project-key.txt
|
|
89
|
+
npx @creeperhost/modlens-mcp --project list --key-file=.gradle/modlens/project-key.txt
|
|
90
|
+
npx @creeperhost/modlens-mcp --project members --environment-id=<returned-id> --class-name=net.minecraft.world.level.Level --key-file=.gradle/modlens/project-key.txt
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
From a checkout, the equivalent is `node dist/cli.js project ...`.
|
|
94
|
+
|
|
95
|
+
For a remote server, run the uploader **on the developer's machine**, where the bundle exists:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx @creeperhost/modlens-mcp --project-upload https://modlens.example/mcp build/modlens/main/environment.zip .gradle/modlens/project-key.txt
|
|
99
|
+
# Checkout equivalent:
|
|
100
|
+
node /path/to/modlens-mcp/scripts/project-upload.mjs https://modlens.example/mcp build/modlens/main/environment.zip .gradle/modlens/project-key.txt
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Set `MODLENS_AUTH_TOKEN` if the deployment's reverse proxy requires a bearer token. Remote uploads require HTTPS; loopback HTTP is supported for local testing. The uploader transfers 1 MiB chunks, verifies the full bundle hash, retries acknowledged chunks safely and prints the imported snapshot metadata. The remote server never runs Gradle or needs the developer's local paths. Host-local import is disabled when `MCP_PORT` is set.
|
|
104
|
+
|
|
105
|
+
Configure the AI to use the MCP **`project` tool** with `projectKey` (the key file's contents) and `environmentId`. Use `project` source/member/search queries for this environment; the existing `mc_source` and `mod` tools continue to describe their shared inputs. Key possession grants access to that project's snapshots; use the deployment's normal authentication to control access to the service and its upload resources.
|
|
106
|
+
|
|
107
|
+
| Action | Additional arguments | Result |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `list` | none | Snapshots belonging to this project key only |
|
|
110
|
+
| `info` | `environmentId` | Versions, artifacts, counts and snapshot provenance |
|
|
111
|
+
| `classes` | `environmentId`, optional `query`, `offset`, `limit` | Classes in compile classpath order of precedence |
|
|
112
|
+
| `source` | `environmentId`, `className`, optional `startLine`, `maxLines` | Supplied Gradle source or an on-demand binary decompile |
|
|
113
|
+
| `members` / `bytecode` | `environmentId`, `className` | Inspection of the project's prepared binary |
|
|
114
|
+
| `search` | `environmentId`, `query`, optional `limit` | Literal, case-insensitive search of supplied sources and cached decompiles |
|
|
115
|
+
| `import_local` | `bundlePath` | Import an absolute host-local ZIP path (stdio only) |
|
|
116
|
+
| `upload_begin` | `size`, `sha256` | Upload ID and chunk size |
|
|
117
|
+
| `upload_chunk` | `uploadId`, `offset`, `data` | Next offset; `data` is base64 |
|
|
118
|
+
| `upload_finish` / `upload_abort` | `uploadId` | Commit a complete upload or remove upload state |
|
|
119
|
+
|
|
120
|
+
Search reports its coverage: a missing match does not prove absence from binaries without sources. Duplicate classes follow the first compile classpath entry; sources from shadowed dependencies are excluded. Multi-release JARs use the compile Java release, with stale base sources excluded when a versioned class overrides them. Limits are 512 MiB per bundle, 1 GiB expanded content, 2 MiB per Java source, and four unfinished uploads per project. Abandoned uploads expire after 24 hours and are cleaned up when the next upload begins. Snapshot files live under `MODLENS_CACHE_ROOT/projects` and work with all database backends.
|
|
121
|
+
|
|
122
|
+
Contributor validation: `npm run test:project:http` exercises the real uploader and HTTP transport. Set `JAVA_HOME` and `MODLENS_TEST_GRADLE_HOME`, then run `npm run test:project:gradle` for a Java dependency fixture, or `npm run test:project:gradle -- moddev` for a real AT before/after check. The Gradle tests use disposable projects and may download build dependencies; they never launch Minecraft.
|
|
123
|
+
|
|
124
|
+
Minecraft compatibility validation: `npm run test:minecraft:eras` exercises the local MCP server across Beta 1.7.3 through 26.1.2, plus real legacy Forge, Fabric and NeoForge mods, using temporary databases and caches. See [TESTING.md](TESTING.md) for the version matrix, offline format coverage and upstream gaps.
|
|
125
|
+
|
|
52
126
|
## Prerequisites
|
|
53
127
|
|
|
54
128
|
| Requirement | Notes |
|
|
@@ -63,7 +137,7 @@ npm run start # start the server
|
|
|
63
137
|
|
|
64
138
|
| Variable | Purpose |
|
|
65
139
|
|----------|---------|
|
|
66
|
-
| `CURSEFORGE_API_KEY` | CurseForge
|
|
140
|
+
| `CURSEFORGE_API_KEY` | Optional direct fingerprint lookup and authenticated CurseForge downloads; normal metadata/sync uses modpacks.ch |
|
|
67
141
|
| `MODRINTH_TOKEN` | Modrinth API — increases rate limit for batch operations |
|
|
68
142
|
| `JAVA_HOME` | Override Java discovery (falls back to PATH if not set) |
|
|
69
143
|
|
|
@@ -154,10 +228,24 @@ node dist/cli.js backfill-embeddings
|
|
|
154
228
|
node dist/cli.js backfill-embeddings --type source --version 26.1.2
|
|
155
229
|
```
|
|
156
230
|
|
|
157
|
-
After this, the `docs` and `primers` MCP tools
|
|
231
|
+
After this, the `docs` and `primers` MCP tools provide `semantic_search`, and `mc_source` provides `search_semantic` and `index_semantic`. Semantic search requires a reachable Ollama service and the configured embedding model. Keyword search remains available separately. SQLite uses the bundled `sqlite-vec` dependency; `db:vector` above is for PostgreSQL.
|
|
158
232
|
|
|
159
233
|
> **Note:** The `npm run db:vector` script is safe to re-run. It creates the `pgvector` extension and `embedding` columns using `IF NOT EXISTS` guards.
|
|
160
234
|
|
|
235
|
+
## Data sources and shared bundles
|
|
236
|
+
|
|
237
|
+
ModLens uses [modpacks.ch](https://modpacks.ch/api/openapi.json) for supported mod and pack searches, provider records, release histories, hash lookups, parsed pack manifests and loader versions. Maven artifacts and metadata come from [CreeperHost Maven](https://maven.creeperhost.net/). Download URLs supplied by modpacks.ch may point to the original provider's CDN. An API failure or missing result does not silently switch to another metadata service.
|
|
238
|
+
|
|
239
|
+
When a mod file has no loader label, loader-filtered searches, version listings and update checks automatically download and inspect its JAR. Existing modpacks.ch labels take precedence. Inspection supports Forge/FML, Fabric, Quilt and NeoForge, including multiple loader declarations in one JAR; unknown or mismatched loaders are excluded. Recovered labels report `loaderSource: "jar"`. The first lookup can download several candidate files; subsequent queries and ingestion reuse the artifact cache. `mod_info` defaults to the latest 20 matches and reports `versionLimit`; increase `limit` (CLI: `--limit`) for more history. Download, checksum and unreadable-JAR failures are reported as errors.
|
|
240
|
+
|
|
241
|
+
Existing sources remain for capabilities these services do not cover: Mojang manifests, game files and official mappings; mcmeta's extracted data and history; RetroMCP legacy mappings; Adoptium runtime provisioning; the ModLens indexer release; metadata-provided source repositories; and the selected GitHub graph and embedding registries. Existing local Java installations are preferred.
|
|
242
|
+
|
|
243
|
+
`mod graph_build` can build a class and inheritance graph directly from the mod JAR, without Graphify or an AI service. Set `backend=ast-only` to select this mode explicitly. `graph_enrich_next` and `graph_enrich_submit` add relationships supplied by the client. Automatic semantic extraction still needs a configured Graphify backend.
|
|
244
|
+
|
|
245
|
+
`graph_export` and `embed_export` produce portable gzip bundles. Pass the resulting `bundlePath` to `graph_submit` or `embed_submit` to propose the bundle and its index entry together in a draft pull request. The defaults are [Mattabase/modlens-graphs](https://github.com/Mattabase/modlens-graphs) and [Mattabase/modlens-embeddings](https://github.com/Mattabase/modlens-embeddings). Submissions require `MODLENS_REGISTRY_TOKEN` or `GITHUB_TOKEN` with access to write the branch and open the pull request; a personal fork is used when the account cannot push to the registry. Submission does not merge the pull request.
|
|
246
|
+
|
|
247
|
+
Custom registries use `MODLENS_GRAPH_REGISTRY_URL` or `MODLENS_EMBED_REGISTRY_URL`. For submission, the corresponding `MODLENS_GRAPH_REGISTRY_REPO` / `MODLENS_EMBED_REGISTRY_REPO`, `_BRANCH` and `_INDEX_PATH` settings override the destination inferred from a GitHub raw-content URL.
|
|
248
|
+
|
|
161
249
|
---
|
|
162
250
|
|
|
163
251
|
## MCP Configuration
|
|
@@ -456,10 +544,10 @@ Run without arguments (or `--help`) to print the full command list. Every MCP to
|
|
|
456
544
|
| `modpacks manifest <packId> <verId>` | Pack manifest |
|
|
457
545
|
| MCP `modpacks_ch action=resolve_pack` | Resolve FTB/CurseForge/Modrinth/Feed The Beast pack names, IDs, version IDs, or version names |
|
|
458
546
|
| MCP `modpacks_ch action=list_versions` | List remote pack versions and optionally mark matches for a short `versionRef` like `7.1` |
|
|
459
|
-
| MCP `modpacks_ch action=ingest_pack` |
|
|
547
|
+
| MCP `modpacks_ch action=ingest_pack` | Resolve metadata through modpacks.ch, then download and ingest the selected pack version |
|
|
460
548
|
| `modpacks list-versions` | Pack version list |
|
|
461
549
|
| `modpacks list-files` | Pack file list |
|
|
462
|
-
| `modpacks
|
|
550
|
+
| `modpacks mod-info <modId>` | Mod metadata from modpacks.ch (`ftb-mod-info` remains an alias) |
|
|
463
551
|
| `modpacks find-mod` | Find a mod across packs |
|
|
464
552
|
|
|
465
553
|
**Diagnostics**
|
|
@@ -568,8 +656,8 @@ All tool actions have been consolidated into **24 grouped tools** to stay within
|
|
|
568
656
|
|
|
569
657
|
| action | Key params | Description |
|
|
570
658
|
|--------|-----------|-------------|
|
|
571
|
-
| `sync_modrinth` | dbId | SHA-
|
|
572
|
-
| `sync_curseforge` | dbId |
|
|
659
|
+
| `sync_modrinth` | dbId | Resolve a known project or JAR SHA-1 through modpacks.ch; store project ID and source URL |
|
|
660
|
+
| `sync_curseforge` | dbId | Resolve a known project or JAR SHA-1 through modpacks.ch; no CurseForge API key required |
|
|
573
661
|
| `check_updates` | dbId | Check both platforms for newer version |
|
|
574
662
|
| `batch_sync` | syncModrinth, syncCurseforge, downloadSources, modIdFilter, limit | Bulk sync all unmatched mods |
|
|
575
663
|
| `download_source` | dbId | Download GitHub/GitLab source ZIP |
|
|
@@ -630,13 +718,23 @@ All tool actions have been consolidated into **24 grouped tools** to stay within
|
|
|
630
718
|
| action | Key params | Description |
|
|
631
719
|
|--------|-----------|-------------|
|
|
632
720
|
| `ingest` | entries[] | Add migration guide entries |
|
|
633
|
-
| `seed` |
|
|
634
|
-
| `get` | id |
|
|
635
|
-
| `by_version` | fromVersion, toVersion, modloader |
|
|
721
|
+
| `seed` | fetchContent=true | Populate the official Minecraft/Forge/NeoForge primer catalogue and cache missing guide bodies |
|
|
722
|
+
| `get` | id, startLine=1, maxLines=400, fetchContent=true, refresh=false | Read cached Markdown; fetch missing content automatically |
|
|
723
|
+
| `by_version` | fromVersion, toVersion, modloader, includeContent=false, maxChars=60000, cursor, fetchContent=true | Ordered migration steps; optionally bundle their Markdown, including vanilla changes for the selected loader |
|
|
636
724
|
| `search` | query, modloader, fromVersion, toVersion, limit | Full-text search |
|
|
637
725
|
| `list` | modloader, limit | List all primers |
|
|
638
726
|
| `delete` | id | Remove by DB id |
|
|
639
727
|
|
|
728
|
+
Start with `{"action":"seed"}` on a fresh database, then use `{"action":"by_version","fromVersion":"1.21.1","toVersion":"1.21.5","modloader":"neoforge"}`. This returns the vanilla and NeoForge guides for the intervening transitions. Call `{"action":"get","id":<returned id>}` for each guide, following `nextStartLine` until it is null. Guides retain headings, tables, links and code blocks; pagination does not truncate the cached document. The catalogue contains the steps published upstream, so a result is not a guarantee of coverage for every release or loader.
|
|
729
|
+
|
|
730
|
+
To read a whole migration range, request `{"action":"by_version","fromVersion":"1.21.1","toVersion":"26.1","modloader":"neoforge","includeContent":true}`. The server fetches missing bodies and returns the original Markdown with each guide's ID, title, source URL, loader and version boundaries. Small ranges fit in one response. Larger ranges return `nextCursor`; repeat the same request with `cursor` set to that value until it is null. `count` is the total number of matching guides; `primers` contains the current page. Existing calls without `includeContent` retain their metadata-only response.
|
|
731
|
+
|
|
732
|
+
Bundled pages share a `maxChars` text budget (1,000–200,000, default 60,000) and contain at most 20 guides. Long guides may span pages: concatenate `content` chunks for the same ID directly, without inserting separators. `startOffset`, `endOffset` (exclusive), `totalChars` and `contentChars` count UTF-16 code units; pagination preserves Unicode characters. Each guide reports `contentStatus` and `truncated`; the outer `truncated` reports whether another page remains. Cursors detect changes to the selected catalogue or partly read content and ask you to restart. `fetchContent:false` reads only cached bodies and reports missing ones with `contentStatus:"missing"` and a page-level `missing` count. Fetch failures retain successful guides, report `contentStatus:"fetch_failed"` and an error per failed guide, and set the page-level `failed` count and MCP error flag. Retry those IDs with `get`. The CLI equivalent is `primers by-version 1.21.1 26.1 --modloader=neoforge --include-content`, with optional `--max-chars=`, `--cursor=` and `--fetch-content=false`; fetch failures set a nonzero exit code after printing the page.
|
|
733
|
+
|
|
734
|
+
`get` and `seed` fetch missing content on the MCP server and store it in its configured database, so this also works with a remote server. Cached reads work without Internet access. Use `fetchContent:false` for metadata-only reads/seeding, or `refresh:true` on `get` to replace cached content. Fetch failures return an error; failed refreshes preserve the previous content. `ingest` still accepts supplied content or an explicit `entries[].fetchContent:true`, and reports failed entries without saving them. The CLI equivalents are `primers seed --fetch-content=false` and `primers get <id> --refresh --start-line=401`.
|
|
735
|
+
|
|
736
|
+
Existing installations repair the old built-in placeholder URLs on the first primer operation; no database reset is needed. IDs are retained where possible, and obsolete duplicates or placeholders are marked superseded with replacement guides. Custom entries and existing content are preserved.
|
|
737
|
+
|
|
640
738
|
### 10. `mc_registry` — MC Registry & Meta Data
|
|
641
739
|
|
|
642
740
|
| action | Key params | Description |
|
|
@@ -836,7 +934,7 @@ modpacks_ch action=ingest_pack namespace=modrinth packRef=<slug-or-project-id
|
|
|
836
934
|
modpacks_ch action=ingest_pack namespace=modrinth packRef="https://modrinth.com/modpack/fabulously-optimized" versionRef=6.4.0
|
|
837
935
|
|
|
838
936
|
# Official Feed The Beast API packs use namespace=feedthebeast.
|
|
839
|
-
#
|
|
937
|
+
# Both use modpacks.ch: namespace=ftb selects /modpack; feedthebeast selects /ftb.
|
|
840
938
|
modpacks_ch action=list_versions namespace=feedthebeast packRef="Architect's" versionRef=1.1
|
|
841
939
|
modpacks_ch action=ingest_pack namespace=feedthebeast packRef="Architect's" versionRef=1.1
|
|
842
940
|
|
|
@@ -942,16 +1040,16 @@ node dist/cli.js check-updates 2
|
|
|
942
1040
|
|
|
943
1041
|
### Services & APIs
|
|
944
1042
|
- **[CreeperHost](https://www.creeperhost.net)** — for the free [modpacks.ch](https://www.modpacks.ch) public API powering modpack search, sync, and mod downloads.
|
|
945
|
-
- **[Feed The Beast](https://www.feed-the-beast.com)** — for the
|
|
1043
|
+
- **[Feed The Beast](https://www.feed-the-beast.com)** — for the official FTB pack catalog, accessed through modpacks.ch.
|
|
946
1044
|
- **[Modrinth](https://modrinth.com)** — for the free [Modrinth API](https://docs.modrinth.com) powering mod search, metadata lookup, and version sync.
|
|
947
|
-
- **[CurseForge](https://www.curseforge.com)** — for
|
|
1045
|
+
- **[CurseForge](https://www.curseforge.com)** — for mod and modpack hosting; metadata and release history are accessed through modpacks.ch.
|
|
948
1046
|
- **[misode](https://github.com/misode)** — for [mcmeta](https://github.com/misode/mcmeta), the version-controlled Minecraft data repository that powers the `mc_data`, `mc_files`, and `mc_registry` tools.
|
|
949
1047
|
- **[Mojang](https://www.minecraft.net)** — for publishing official Mojmap mappings and the Piston Meta API used for version discovery and JAR downloads.
|
|
950
1048
|
|
|
951
1049
|
### Modloader teams
|
|
952
|
-
- **[NeoForged team](https://github.com/neoforged/NeoForge)** — for NeoForge, the [NeoForge documentation](https://docs.neoforged.net) seeded into the docs database, and the migration
|
|
1050
|
+
- **[NeoForged team](https://github.com/neoforged/NeoForge)** — for NeoForge, the [NeoForge documentation](https://docs.neoforged.net) seeded into the docs database, and the [migration primer catalogue](https://docs.neoforged.net/primer/docs/) used by the primers tool.
|
|
953
1051
|
- **[FabricMC team](https://github.com/FabricMC)** — for the [Fabric Wiki](https://fabricmc.net/wiki) and [Yarn mappings](https://github.com/FabricMC/yarn) seeded into the docs database, Intermediary mappings used by the `mappings` tool, and [mcsrc.dev](https://mcsrc.dev) whose source browsing and class analysis features inspired our `mc_source` tool.
|
|
954
|
-
- **[MinecraftForge team](https://github.com/MinecraftForge)** — for
|
|
1052
|
+
- **[MinecraftForge team](https://github.com/MinecraftForge)** — for Forge and the API changes documented in the Forge migration primers.
|
|
955
1053
|
|
|
956
1054
|
### Community contributors
|
|
957
1055
|
- **[MCPHackers](https://mcphackers.org/)** — for [RetroMCP](https://github.com/MCPHackers/RetroMCP-Java), providing the Tiny v2 mappings that enable decompilation of legacy Minecraft versions (Alpha, Beta, and pre-1.7.10 releases).
|
|
@@ -977,4 +1075,3 @@ node dist/cli.js check-updates 2
|
|
|
977
1075
|
### Special thanks
|
|
978
1076
|
|
|
979
1077
|
A heartfelt thank you to all the members of the **ForgeCraft Discord and Minecraft server** for being a genuinely great community, for your feedback, and for supporting my development endeavours over the years. This project wouldn't be what it is without you.
|
|
980
|
-
|
package/TESTING.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Compatibility testing
|
|
2
|
+
|
|
3
|
+
Run the deterministic regressions with `npm test`. Run `npm run build` before the MCP and package checks below.
|
|
4
|
+
|
|
5
|
+
`npm test` works directly after `npm ci`, before a build. Vitest generates the SQLite client before importing the tests. SQLite integration tests create a temporary template from the Prisma schema, use a fresh database for each test, and isolate their artifact cache. They do not depend on `dist/`, the packaged `template.db`, or earlier test results.
|
|
6
|
+
|
|
7
|
+
## Minecraft era matrix
|
|
8
|
+
|
|
9
|
+
`npm run test:minecraft:eras` starts a local MCP server with a fresh temporary SQLite database, home and cache. It downloads public artifacts using the application's configured source policy. Every interaction with game/mod source goes through MCP. Results and the server log are retained in the printed temporary directory.
|
|
10
|
+
|
|
11
|
+
The vanilla checks verify named class discovery, decompiled source, methods/fields, bytecode and inheritance:
|
|
12
|
+
|
|
13
|
+
| Mapping generation | Minecraft versions |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| RetroMCP, separate client/server namespaces | Beta 1.7.3, 1.2.5 |
|
|
16
|
+
| RetroMCP, joined mappings | 1.5.2 |
|
|
17
|
+
| Legacy SRG, with MCP member names where available | 1.6.4, 1.7.10, 1.8.9, 1.12.2 |
|
|
18
|
+
| MCPConfig TSRG | 1.13.2 |
|
|
19
|
+
| Official Mojang mappings | 1.16.5, 1.18.2, 1.20.1, 1.20.6, 1.21.1 |
|
|
20
|
+
| Unobfuscated game artifacts | 26.1.2 |
|
|
21
|
+
|
|
22
|
+
The 1.5.2 checks also verify the explicit `MinecraftServer.tick` and `IntegratedServer.tickIntegrated` mappings. This catches differences between the joined mapping's declared names and TinyRemapper's inherited-name guesses.
|
|
23
|
+
|
|
24
|
+
Real-mod checks cover metadata resolution, the compatibility action alias, download/ingestion, database identity, language discovery, indexing, members, bytecode and single-class decompilation:
|
|
25
|
+
|
|
26
|
+
| Mod | Minecraft / loader |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| Waila | 1.6.4 Forge, 1.7.10 Forge |
|
|
29
|
+
| JEI | 1.8.9 Forge, 1.12.2 Forge, 1.16.5 Forge, 1.20.1 Forge, 1.21.1 NeoForge |
|
|
30
|
+
| Sodium | 1.16.5 Fabric |
|
|
31
|
+
|
|
32
|
+
Select individual game versions or run only the mod checks:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm run test:minecraft:eras -- b1.7.3 1.7.10 1.12.2
|
|
36
|
+
npm run test:minecraft:eras -- --mods
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Set `JAVA_HOME` for the Java runtime used by remapping. Public services must be reachable. Optional `MODLENS_TEST_TOOL_CACHE` and `MODLENS_TEST_ARTIFACT_CACHE` directories are read-only seeds: the harness copies their files into its temporary cache. Credentials, live database settings, MCP server settings and automatic graph/embedding settings are removed from the test server environment. The harness retains evidence and never starts Minecraft gameplay.
|
|
40
|
+
|
|
41
|
+
## Offline format regressions
|
|
42
|
+
|
|
43
|
+
The unit suite builds small disposable JARs and mapping archives. Assertions cover the behavior that changed between eras:
|
|
44
|
+
|
|
45
|
+
- `mcmod.info` arrays, wrapper objects and bare objects from 1.2.5 through 1.12.2.
|
|
46
|
+
- Java 6/7/8 Forge annotations, accepted Minecraft ranges, required versus optional dependencies, version bounds and duplicate declarations.
|
|
47
|
+
- Legacy `FMLAT` files and folded JAR manifest headers.
|
|
48
|
+
- Forge `mods.toml`, JAR implementation-version substitution, early NeoForge `mods.toml` and later `neoforge.mods.toml` dependency types.
|
|
49
|
+
- Fabric declared mixin filenames, optional dependencies, array predicates and access wideners; Quilt metadata, dependencies and its `mixin` key.
|
|
50
|
+
- SRG/TSRG archives, MCP CSV names, object descriptors, CRLF mappings and consistency between version listing and source access.
|
|
51
|
+
- Pre-1.13 resources under `assets/`, later data packs under `data/`, and the 1.21 plural-to-singular directory changes.
|
|
52
|
+
- Legacy `.lang` files, JSON translations, namespace filtering and resource deduplication.
|
|
53
|
+
- Automatic loader inspection for unlabeled files, provider-label precedence, multiple loader declarations, pagination after filtering, artifact reuse, forced refresh, checksum failures and range-filtered update checks.
|
|
54
|
+
|
|
55
|
+
## Package validation
|
|
56
|
+
|
|
57
|
+
`npm run test:package` installs the packed npm artifact into an isolated consumer. It checks setup, the MCP handshake, SQLite bootstrap, database types, transactions and restart persistence. Run this after changes to public commands, packaging or database setup.
|
|
58
|
+
|
|
59
|
+
## Current coverage and upstream gaps
|
|
60
|
+
|
|
61
|
+
The 2026-09-13 housekeeping and loader-fallback passes verified the matrix above. These are selected compatibility boundaries, not an exhaustive test of every Minecraft release or mod.
|
|
62
|
+
|
|
63
|
+
Clean-install validation on 2026-09-13 passed `npm ci` → `npm test` (523 tests across 28 files) → `npm run build` on Ubuntu 24.04 and Windows using Node 22.21.1. The SQLite suite also passed in shuffled order, and the schema-repair test passed on its own.
|
|
64
|
+
|
|
65
|
+
The final mod matrix passed 116 MCP checks across all eight builds, including filtered search, mismatch rejection and database isolation. The installed npm-consumer checks also passed.
|
|
66
|
+
|
|
67
|
+
Some modpacks.ch historical file records, including the tested Waila releases and JEI 1.8.9, include the Minecraft version but omit the loader target. The matrix now supplies the loader filter for every release. ModLens keeps the API's version order, uses supplied loader labels, and downloads and inspects unlabeled candidate JARs before accepting a match. Result limits apply after filtering, including across pages. This also recovers a newer unlabeled file when older labeled versions exist.
|
|
68
|
+
|
|
69
|
+
The fallback is automatic for mod searches, details, downloads and provider update checks. Recovered labels carry `loaderSource: "jar"`; the artifact cache is shared with ingestion. `mod_info` returns up to 20 matches by default; its `limit` parameter allows a larger history. The MCP matrix also checks loader-filtered Waila search, rejects Waila for Fabric, and verifies that metadata inspection does not ingest candidates into the database. JARs with no recognised loader are excluded, and failed downloads or unreadable artifacts produce errors. API errors still surface, and no other metadata service supplies replacement records. Upstream labels can be populated later; they take precedence immediately when present.
|
package/dist/cli.js
CHANGED
|
@@ -23,13 +23,14 @@ import { getModGradleFiles, searchGradleFiles, compareGradleDeps } from "./tools
|
|
|
23
23
|
import { generateReport } from "./tools/reports.js";
|
|
24
24
|
import { findAssetConflicts, findVanillaOverrides, analyzeModSidedness, analyzePackSidedness, computeModComplexity, computePackChangelog, findDataConflicts } from "./tools/packtools.js";
|
|
25
25
|
import { indexKubeJsScripts, searchKubeJsScripts } from "./tools/kubejs.js";
|
|
26
|
-
import { searchPacksAction, featuredPacksAction, packInfoAction, packManifestAction,
|
|
26
|
+
import { searchPacksAction, featuredPacksAction, packInfoAction, packManifestAction, modInfoAction, listPackVersionsAction, listPackFilesAction, findModInPacksAction, } from "./tools/modpacks-ch.js";
|
|
27
27
|
import { analyzeCrashLog, findMissingDeps } from "./tools/diagnostics.js";
|
|
28
28
|
import { checkModCompat } from "./tools/compat-check.js";
|
|
29
29
|
import { listModJarFiles, getModJarFile, getModLang, getModSounds, getModAtlas, getModManifest, listModConfigs, getModConfig, listModData, getModData, listModDataTags, getModDataTag, getModModel as getModModelData, diffModData, traceRecipeChain, } from "./tools/mod-data.js";
|
|
30
30
|
import { mcPaths } from "./minecraft.js";
|
|
31
31
|
import { findModById } from "./repositories/mod.js";
|
|
32
32
|
import { CACHE_ROOT } from "./cache.js";
|
|
33
|
+
import { projectAction } from "./tools/project.js";
|
|
33
34
|
import { getDb, disconnect } from "./db.js";
|
|
34
35
|
import { readdir, readFile } from "fs/promises";
|
|
35
36
|
import { join, resolve } from "path";
|
|
@@ -211,9 +212,11 @@ DOCS
|
|
|
211
212
|
docs semantic-search <query> Semantic search (requires Ollama) [--limit=10]
|
|
212
213
|
|
|
213
214
|
PRIMERS (version migration guides)
|
|
214
|
-
primers seed Seed built-in
|
|
215
|
-
primers get <id>
|
|
215
|
+
primers seed Seed and fetch built-in primers [--fetch-content=false]
|
|
216
|
+
primers get <id> Read cached/fetched Markdown [--refresh] [--fetch-content=false]
|
|
217
|
+
[--start-line=1] [--max-lines=400]
|
|
216
218
|
primers by-version <from> <to> Get primers for a version range [--modloader=]
|
|
219
|
+
[--include-content] [--max-chars=60000] [--cursor=] [--fetch-content=false]
|
|
217
220
|
primers search <query> Keyword search [--modloader=] [--limit=]
|
|
218
221
|
primers list List all primers [--modloader=] [--limit=]
|
|
219
222
|
primers delete <id> Delete a primer by ID
|
|
@@ -291,6 +294,10 @@ MOD TAGS (cross-mod data-pack tags)
|
|
|
291
294
|
mod-tags search <query> Search tags [--registry=] [--limit=]
|
|
292
295
|
|
|
293
296
|
GRADLE
|
|
297
|
+
project import-local <bundle.zip> --key-file=<file> Import a private Gradle environment
|
|
298
|
+
project list --key-file=<file> List this project's snapshots
|
|
299
|
+
project info|classes|source|search|members|bytecode --key-file=<file> --environment-id=<id>
|
|
300
|
+
[--class-name=<name>] [--query=<text>] [--limit=20] [--offset=0] [--start-line=1] [--max-lines=200]
|
|
294
301
|
gradle get-files <modId> Extract Gradle build files
|
|
295
302
|
gradle search <query> Search Gradle files across mods [--mod-id-filter=] [--limit=]
|
|
296
303
|
gradle compare-deps Compare dependency versions across mods [--group-filter=] [--mod-id-filter=]
|
|
@@ -327,7 +334,7 @@ MODPACKS.CH
|
|
|
327
334
|
modpacks manifest <packId> <verId> Pack manifest [--namespace=]
|
|
328
335
|
modpacks list-versions Pack version list [--namespace=] [--pack-id=]
|
|
329
336
|
modpacks list-files Pack file list [--namespace=] [--pack-id=] [--version-id=] [--file-type=]
|
|
330
|
-
modpacks
|
|
337
|
+
modpacks mod-info <modId> Mod metadata [--mc-version=] [--loader=] [--limit=20]
|
|
331
338
|
modpacks find-mod Find a mod across packs [--mod-db-id=] [--cf-project=]
|
|
332
339
|
|
|
333
340
|
DIAGNOSTICS
|
|
@@ -862,15 +869,33 @@ try {
|
|
|
862
869
|
case "primers": {
|
|
863
870
|
const sub = requireArg(positional[0], "primers action");
|
|
864
871
|
switch (sub) {
|
|
865
|
-
case "seed":
|
|
866
|
-
|
|
872
|
+
case "seed": {
|
|
873
|
+
const seeded = await seedDefaultPrimers(flags.fetchContent !== "false" && flags.fetchContent !== false);
|
|
874
|
+
out(seeded);
|
|
875
|
+
if (seeded.failed)
|
|
876
|
+
process.exitCode = 1;
|
|
867
877
|
break;
|
|
878
|
+
}
|
|
868
879
|
case "get":
|
|
869
|
-
out(await getPrimer(numArg(positional[1], "id")
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
880
|
+
out(await getPrimer(numArg(positional[1], "id"), {
|
|
881
|
+
fetchContent: flags.fetchContent !== "false" && flags.fetchContent !== false,
|
|
882
|
+
refresh: flags.refresh === true || flags.refresh === "true",
|
|
883
|
+
startLine: flags.startLine,
|
|
884
|
+
maxLines: flags.maxLines,
|
|
885
|
+
}));
|
|
886
|
+
break;
|
|
887
|
+
case "by-version": {
|
|
888
|
+
const range = await getPrimersByVersionRange(requireArg(positional[1], "fromVersion"), requireArg(positional[2], "toVersion"), flags.modloader, {
|
|
889
|
+
includeContent: flags.includeContent === true || flags.includeContent === "true",
|
|
890
|
+
fetchContent: flags.fetchContent !== "false" && flags.fetchContent !== false,
|
|
891
|
+
maxChars: flags.maxChars,
|
|
892
|
+
cursor: flags.cursor,
|
|
893
|
+
});
|
|
894
|
+
out(range);
|
|
895
|
+
if ("failed" in range && range.failed)
|
|
896
|
+
process.exitCode = 1;
|
|
873
897
|
break;
|
|
898
|
+
}
|
|
874
899
|
case "search":
|
|
875
900
|
out(await searchPrimers(requireArg(positional[1], "query"), flags.modloader, undefined, undefined, flags.limit));
|
|
876
901
|
break;
|
|
@@ -1144,6 +1169,16 @@ try {
|
|
|
1144
1169
|
break;
|
|
1145
1170
|
}
|
|
1146
1171
|
// ── Gradle ────────────────────────────────────────────────────────────
|
|
1172
|
+
case "project": {
|
|
1173
|
+
const action = requireArg(positional[0], "project action").replace(/-/g, "_");
|
|
1174
|
+
const keyFile = requireArg(typeof flags.keyFile === "string" ? flags.keyFile : undefined, "--key-file=/path/to/project-key.txt");
|
|
1175
|
+
const projectKey = (await readFile(resolve(keyFile), "utf8")).trim();
|
|
1176
|
+
const { keyFile: ignored, ...options } = flags;
|
|
1177
|
+
out(await projectAction({ ...options, action, projectKey,
|
|
1178
|
+
...(action === "import_local" ? { bundlePath: resolve(requireArg(positional[1], "bundle.zip")) } : {}),
|
|
1179
|
+
}));
|
|
1180
|
+
break;
|
|
1181
|
+
}
|
|
1147
1182
|
case "gradle": {
|
|
1148
1183
|
const sub = requireArg(positional[0], "gradle action");
|
|
1149
1184
|
switch (sub) {
|
|
@@ -1253,14 +1288,15 @@ try {
|
|
|
1253
1288
|
case "list-files":
|
|
1254
1289
|
out(await listPackFilesAction({ namespace: flags.namespace, packId: flags.packId, versionId: flags.versionId, fileType: flags.fileType }));
|
|
1255
1290
|
break;
|
|
1256
|
-
case "
|
|
1257
|
-
|
|
1291
|
+
case "mod-info":
|
|
1292
|
+
case "ftb-mod-info": // Compatibility with older CLI clients.
|
|
1293
|
+
out(await modInfoAction(modIdArg(positional[1], "modId"), { mcVersion: flags.mcVersion, loader: flags.loader, limit: flags.limit }));
|
|
1258
1294
|
break;
|
|
1259
1295
|
case "find-mod":
|
|
1260
1296
|
out(await findModInPacksAction({ modDbId: flags.modDbId, cfProject: flags.cfProject }));
|
|
1261
1297
|
break;
|
|
1262
1298
|
default:
|
|
1263
|
-
die(`Unknown modpacks action: ${sub}. Use: search|featured|info|manifest|list-versions|list-files|
|
|
1299
|
+
die(`Unknown modpacks action: ${sub}. Use: search|featured|info|manifest|list-versions|list-files|mod-info|find-mod`);
|
|
1264
1300
|
}
|
|
1265
1301
|
break;
|
|
1266
1302
|
}
|