@adhisang/minecraft-modding-mcp 6.2.0 → 7.0.0-rc.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/CHANGELOG.md +71 -0
- package/README.md +21 -5
- package/dist/cache-policy.d.ts +71 -0
- package/dist/cache-policy.js +83 -0
- package/dist/cache-registry.js +6 -6
- package/dist/cli.js +74 -3
- package/dist/compat-stdio-transport.d.ts +1 -1
- package/dist/compat-stdio-transport.js +13 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +8 -2
- package/dist/decompiler/vineflower.d.ts +1 -0
- package/dist/decompiler/vineflower.js +8 -5
- package/dist/entry-tools/analyze-mod-service.d.ts +70 -136
- package/dist/entry-tools/analyze-symbol-service.d.ts +112 -150
- package/dist/entry-tools/compare-minecraft-service.d.ts +59 -145
- package/dist/entry-tools/entry-tool-schema.d.ts +38 -4
- package/dist/entry-tools/entry-tool-schema.js +4 -1
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +235 -799
- package/dist/entry-tools/inspect-minecraft/internal.js +65 -28
- package/dist/entry-tools/inspect-minecraft-service.d.ts +372 -1736
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +81 -91
- package/dist/entry-tools/validate-project/cases/project-summary.d.ts +7 -7
- package/dist/entry-tools/validate-project-service.d.ts +164 -592
- package/dist/entry-tools/verify-mixin-target-service.d.ts +3 -19
- package/dist/era-classifier.d.ts +161 -0
- package/dist/era-classifier.js +292 -0
- package/dist/error-mapping.js +9 -2
- package/dist/index.d.ts +42 -4
- package/dist/index.js +637 -475
- package/dist/java-process.d.ts +2 -0
- package/dist/java-process.js +22 -2
- package/dist/json-rpc-framing.d.ts +77 -1
- package/dist/json-rpc-framing.js +249 -13
- package/dist/mapping/loaders/tiny-loom-selection.d.ts +88 -0
- package/dist/mapping/loaders/tiny-loom-selection.js +223 -0
- package/dist/mapping/loaders/tiny-loom.js +45 -33
- package/dist/mapping/loaders/tiny-maven.js +6 -11
- package/dist/mapping/parsers/tiny.d.ts +57 -0
- package/dist/mapping/parsers/tiny.js +99 -22
- package/dist/mapping-service.d.ts +19 -0
- package/dist/mapping-service.js +93 -9
- package/dist/mcp-helpers.d.ts +19 -2
- package/dist/mcp-helpers.js +48 -6
- package/dist/minecraft-explorer-service.d.ts +1 -1
- package/dist/mixin/types.d.ts +8 -0
- package/dist/mod-analyzer.js +7 -7
- package/dist/mod-decompile-service.js +1 -0
- package/dist/nbt/java-nbt-codec.js +12 -2
- package/dist/nbt/json-patch.js +14 -3
- package/dist/nbt/pipeline.js +40 -3
- package/dist/nbt/typed-json.js +26 -1
- package/dist/registration-adapter.d.ts +32 -0
- package/dist/registration-adapter.js +52 -0
- package/dist/request-context.d.ts +7 -0
- package/dist/request-context.js +9 -0
- package/dist/resources.d.ts +1 -1
- package/dist/resources.js +25 -19
- package/dist/server-identity.d.ts +27 -0
- package/dist/server-identity.js +26 -0
- package/dist/source/access-validate.js +53 -0
- package/dist/source/artifact-resolver.d.ts +69 -1
- package/dist/source/artifact-resolver.js +215 -14
- package/dist/source/class-source.d.ts +22 -0
- package/dist/source/class-source.js +162 -29
- package/dist/source/did-you-mean.d.ts +12 -1
- package/dist/source/did-you-mean.js +6 -2
- package/dist/source/file-access.js +150 -46
- package/dist/source/indexer.js +1 -0
- package/dist/source/nested-jars.d.ts +19 -0
- package/dist/source/nested-jars.js +90 -21
- package/dist/source/shared-utils.d.ts +21 -0
- package/dist/source/shared-utils.js +23 -0
- package/dist/source-service.d.ts +12 -0
- package/dist/source-service.js +3 -0
- package/dist/stdio-supervisor.d.ts +357 -2
- package/dist/stdio-supervisor.js +1031 -80
- package/dist/storage/db.d.ts +2 -1
- package/dist/storage/db.js +15 -8
- package/dist/synthetic-decorator.d.ts +24 -0
- package/dist/synthetic-decorator.js +48 -0
- package/dist/tool-contract-manifest.js +1 -1
- package/dist/tool-guidance.d.ts +17 -1
- package/dist/tool-guidance.js +417 -13
- package/dist/tool-schema-registry.d.ts +2 -0
- package/dist/tool-schema-registry.js +4 -0
- package/dist/tool-schemas.d.ts +2214 -3915
- package/dist/tool-schemas.js +34 -7
- package/dist/types.d.ts +35 -0
- package/dist/v1-parity-schemas.d.ts +7 -0
- package/dist/v1-parity-schemas.js +5584 -0
- package/dist/version-diff-service.d.ts +33 -0
- package/dist/version-diff-service.js +148 -3
- package/dist/version-service.js +36 -14
- package/dist/warning-details.js +18 -1
- package/docs/README-ja.md +9 -3
- package/docs/tool-reference.md +267 -22
- package/package.json +12 -9
|
@@ -2,6 +2,17 @@ import { VersionService } from "./version-service.js";
|
|
|
2
2
|
import { RegistryService } from "./registry-service.js";
|
|
3
3
|
import type { Config } from "./types.js";
|
|
4
4
|
export type CompareVersionsCategory = "classes" | "registry" | "all";
|
|
5
|
+
/**
|
|
6
|
+
* Namespace the compared class names live in.
|
|
7
|
+
*
|
|
8
|
+
* A vanilla client jar for an obfuscated release lists `dlp.class`, not
|
|
9
|
+
* `net/minecraft/world/item/Item.class`, so a diff taken straight off the jar
|
|
10
|
+
* entries answers in obfuscated names. Every caller-facing name — the `added`
|
|
11
|
+
* and `removed` lists AND `packageFilter` — is expressed in mojang names when
|
|
12
|
+
* the official mappings for both versions can be loaded, and the namespace is
|
|
13
|
+
* always reported so a zero result is never ambiguous.
|
|
14
|
+
*/
|
|
15
|
+
export type ClassDiffNamespace = "mojang" | "obfuscated";
|
|
5
16
|
export type CompareVersionsInput = {
|
|
6
17
|
fromVersion: string;
|
|
7
18
|
toVersion: string;
|
|
@@ -18,6 +29,15 @@ export type CompareVersionsOutput = {
|
|
|
18
29
|
addedCount: number;
|
|
19
30
|
removedCount: number;
|
|
20
31
|
unchanged: number;
|
|
32
|
+
/** Namespace the class names above (and any packageFilter) are expressed in. */
|
|
33
|
+
namespace: ClassDiffNamespace;
|
|
34
|
+
/** Present only when the caller passed packageFilter; reports what it matched. */
|
|
35
|
+
packageFilter?: {
|
|
36
|
+
value: string;
|
|
37
|
+
namespace: ClassDiffNamespace;
|
|
38
|
+
matchedFrom: number;
|
|
39
|
+
matchedTo: number;
|
|
40
|
+
};
|
|
21
41
|
};
|
|
22
42
|
registry?: {
|
|
23
43
|
added: Record<string, string[]>;
|
|
@@ -36,6 +56,19 @@ export declare class VersionDiffService {
|
|
|
36
56
|
private readonly config;
|
|
37
57
|
private readonly versionService;
|
|
38
58
|
private readonly registryService;
|
|
59
|
+
private readonly mojangClassMaps;
|
|
39
60
|
constructor(config: Config, versionService: VersionService, registryService: RegistryService);
|
|
61
|
+
/**
|
|
62
|
+
* obfuscated -> mojang class map for one version, or undefined when the
|
|
63
|
+
* official mappings cannot be obtained (offline, or a release that publishes
|
|
64
|
+
* none). Never throws: a missing map degrades the diff to obfuscated names
|
|
65
|
+
* with a warning rather than failing the comparison.
|
|
66
|
+
*/
|
|
67
|
+
private loadMojangClassMap;
|
|
68
|
+
/**
|
|
69
|
+
* Lifts one version's jar class list into mojang names when possible.
|
|
70
|
+
* Returns the namespace the returned set is actually expressed in.
|
|
71
|
+
*/
|
|
72
|
+
private toMojangNames;
|
|
40
73
|
compareVersions(input: CompareVersionsInput): Promise<CompareVersionsOutput>;
|
|
41
74
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
1
2
|
import { createError, ERROR_CODES } from "./errors.js";
|
|
2
3
|
import { log } from "./logger.js";
|
|
4
|
+
import { resolveMojangTinyFile } from "./mojang-tiny-mapping-service.js";
|
|
3
5
|
import { listJarEntries } from "./source-jar-reader.js";
|
|
4
6
|
const DEFAULT_MAX_CLASS_RESULTS = 500;
|
|
5
7
|
const MAX_CLASS_RESULTS_LIMIT = 5000;
|
|
@@ -25,6 +27,49 @@ function filterByPackage(classes, prefix) {
|
|
|
25
27
|
function filterSetByPackage(classes, prefix) {
|
|
26
28
|
return new Set(filterByPackage([...classes], prefix));
|
|
27
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* True when the jar's class names are obfuscated.
|
|
32
|
+
*
|
|
33
|
+
* Obfuscation collapses every Minecraft class into the DEFAULT package with a
|
|
34
|
+
* short generated name (`dlp`, `ije`), so a jar where a large share of the
|
|
35
|
+
* classes carry no package at all is obfuscated. Unobfuscated releases, jars
|
|
36
|
+
* remapped before listing, and ordinary library/mod jars all keep real package
|
|
37
|
+
* structure and need no mapping load.
|
|
38
|
+
*/
|
|
39
|
+
function looksObfuscated(classes) {
|
|
40
|
+
if (classes.size === 0) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
let defaultPackage = 0;
|
|
44
|
+
for (const fqn of classes) {
|
|
45
|
+
if (!fqn.includes(".")) {
|
|
46
|
+
defaultPackage += 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return defaultPackage > 0 && defaultPackage * 4 >= classes.size;
|
|
50
|
+
}
|
|
51
|
+
/** Parses the `c<TAB>obf<TAB>mojang` rows of a merged mojang tiny v2 file. */
|
|
52
|
+
function parseTinyClassRows(content) {
|
|
53
|
+
const classMap = new Map();
|
|
54
|
+
for (const line of content.split("\n")) {
|
|
55
|
+
if (line.charCodeAt(0) !== 99 /* 'c' */ || line.charCodeAt(1) !== 9 /* TAB */) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const parts = line.split("\t");
|
|
59
|
+
if (parts.length < 3) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const obfuscated = parts[1];
|
|
63
|
+
const mojang = parts[2];
|
|
64
|
+
if (!obfuscated || !mojang) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
classMap.set(obfuscated.replaceAll("/", "."), mojang.replaceAll("/", "."));
|
|
68
|
+
}
|
|
69
|
+
return classMap;
|
|
70
|
+
}
|
|
71
|
+
/** Bounded per-process memo so a repeated comparison re-reads nothing. */
|
|
72
|
+
const MOJANG_CLASS_MAP_CACHE_LIMIT = 4;
|
|
28
73
|
function diffSets(from, to) {
|
|
29
74
|
const added = [];
|
|
30
75
|
const removed = [];
|
|
@@ -128,11 +173,76 @@ export class VersionDiffService {
|
|
|
128
173
|
config;
|
|
129
174
|
versionService;
|
|
130
175
|
registryService;
|
|
176
|
+
mojangClassMaps = new Map();
|
|
131
177
|
constructor(config, versionService, registryService) {
|
|
132
178
|
this.config = config;
|
|
133
179
|
this.versionService = versionService;
|
|
134
180
|
this.registryService = registryService;
|
|
135
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* obfuscated -> mojang class map for one version, or undefined when the
|
|
184
|
+
* official mappings cannot be obtained (offline, or a release that publishes
|
|
185
|
+
* none). Never throws: a missing map degrades the diff to obfuscated names
|
|
186
|
+
* with a warning rather than failing the comparison.
|
|
187
|
+
*/
|
|
188
|
+
async loadMojangClassMap(version) {
|
|
189
|
+
const cached = this.mojangClassMaps.get(version);
|
|
190
|
+
if (cached) {
|
|
191
|
+
return cached;
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const { path } = await resolveMojangTinyFile(version, this.config, {
|
|
195
|
+
versionService: this.versionService
|
|
196
|
+
});
|
|
197
|
+
const classMap = parseTinyClassRows(await readFile(path, "utf8"));
|
|
198
|
+
if (classMap.size === 0) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
if (this.mojangClassMaps.size >= MOJANG_CLASS_MAP_CACHE_LIMIT) {
|
|
202
|
+
const oldest = this.mojangClassMaps.keys().next().value;
|
|
203
|
+
if (oldest !== undefined) {
|
|
204
|
+
this.mojangClassMaps.delete(oldest);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.mojangClassMaps.set(version, classMap);
|
|
208
|
+
return classMap;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
log("warn", "version-diff.mojang_class_map_unavailable", {
|
|
212
|
+
version,
|
|
213
|
+
error: error instanceof Error ? error.message : String(error)
|
|
214
|
+
});
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Lifts one version's jar class list into mojang names when possible.
|
|
220
|
+
* Returns the namespace the returned set is actually expressed in.
|
|
221
|
+
*/
|
|
222
|
+
async toMojangNames(version, classes) {
|
|
223
|
+
if (!looksObfuscated(classes)) {
|
|
224
|
+
return { classes, namespace: "mojang", unmapped: 0 };
|
|
225
|
+
}
|
|
226
|
+
const classMap = await this.loadMojangClassMap(version);
|
|
227
|
+
if (!classMap) {
|
|
228
|
+
return { classes, namespace: "obfuscated", unmapped: classes.size };
|
|
229
|
+
}
|
|
230
|
+
const mapped = new Set();
|
|
231
|
+
let unmapped = 0;
|
|
232
|
+
for (const fqn of classes) {
|
|
233
|
+
const mojang = classMap.get(fqn);
|
|
234
|
+
if (mojang) {
|
|
235
|
+
mapped.add(mojang);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Library classes shipped inside the jar (and anything the mappings do
|
|
239
|
+
// not cover) keep the name the jar carries; they are already readable.
|
|
240
|
+
mapped.add(fqn);
|
|
241
|
+
unmapped += 1;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return { classes: mapped, namespace: "mojang", unmapped };
|
|
245
|
+
}
|
|
136
246
|
async compareVersions(input) {
|
|
137
247
|
const fromVersion = input.fromVersion.trim();
|
|
138
248
|
const toVersion = input.toVersion.trim();
|
|
@@ -168,14 +278,38 @@ export class VersionDiffService {
|
|
|
168
278
|
listJarEntries(fromJar.jarPath),
|
|
169
279
|
listJarEntries(toJar.jarPath)
|
|
170
280
|
]);
|
|
171
|
-
|
|
172
|
-
|
|
281
|
+
// The class names must be lifted OUT of the jar's own namespace
|
|
282
|
+
// before anything is compared or filtered: a mojang packageFilter
|
|
283
|
+
// against obfuscated jar entries matched nothing and reported a
|
|
284
|
+
// silent all-zero diff that read as "no changes".
|
|
285
|
+
const [fromNames, toNames] = await Promise.all([
|
|
286
|
+
this.toMojangNames(fromVersion, extractClassEntries(fromEntries)),
|
|
287
|
+
this.toMojangNames(toVersion, extractClassEntries(toEntries))
|
|
288
|
+
]);
|
|
289
|
+
const namespace = fromNames.namespace === "mojang" && toNames.namespace === "mojang"
|
|
290
|
+
? "mojang"
|
|
291
|
+
: "obfuscated";
|
|
292
|
+
if (namespace === "obfuscated") {
|
|
293
|
+
warnings.push(`Official Mojang mappings could not be loaded for ${fromNames.namespace === "obfuscated" ? fromVersion : toVersion}, so class names (and packageFilter) are compared in the OBFUSCATED namespace. Deobfuscated prefixes such as "net.minecraft.world.item" cannot match here.`);
|
|
294
|
+
}
|
|
295
|
+
const fromClasses = fromNames.classes;
|
|
296
|
+
const toClasses = toNames.classes;
|
|
173
297
|
const filteredFromClasses = input.packageFilter
|
|
174
298
|
? filterSetByPackage(fromClasses, input.packageFilter)
|
|
175
299
|
: fromClasses;
|
|
176
300
|
const filteredToClasses = input.packageFilter
|
|
177
301
|
? filterSetByPackage(toClasses, input.packageFilter)
|
|
178
302
|
: toClasses;
|
|
303
|
+
if (input.packageFilter && filteredFromClasses.size === 0 && filteredToClasses.size === 0) {
|
|
304
|
+
// An empty diff and a non-matching filter look identical on the
|
|
305
|
+
// wire, so the filter has to say which one happened.
|
|
306
|
+
warnings.push(`packageFilter "${input.packageFilter}" matched no class in either ${fromVersion} or ${toVersion}; ` +
|
|
307
|
+
`the reported zeros mean "filter matched nothing", not "nothing changed". ` +
|
|
308
|
+
`Class names are compared in the ${namespace} namespace — ` +
|
|
309
|
+
(namespace === "obfuscated"
|
|
310
|
+
? "an obfuscated jar has no package structure to filter on, so omit packageFilter."
|
|
311
|
+
: "check the package prefix spelling, e.g. \"net.minecraft.world.item\"."));
|
|
312
|
+
}
|
|
179
313
|
const { added, removed, unchanged } = diffSets(filteredFromClasses, filteredToClasses);
|
|
180
314
|
const truncatedAdded = added.slice(0, maxClassResults);
|
|
181
315
|
const truncatedRemoved = removed.slice(0, maxClassResults);
|
|
@@ -190,7 +324,18 @@ export class VersionDiffService {
|
|
|
190
324
|
removed: truncatedRemoved,
|
|
191
325
|
addedCount: added.length,
|
|
192
326
|
removedCount: removed.length,
|
|
193
|
-
unchanged
|
|
327
|
+
unchanged,
|
|
328
|
+
namespace,
|
|
329
|
+
...(input.packageFilter
|
|
330
|
+
? {
|
|
331
|
+
packageFilter: {
|
|
332
|
+
value: input.packageFilter,
|
|
333
|
+
namespace,
|
|
334
|
+
matchedFrom: filteredFromClasses.size,
|
|
335
|
+
matchedTo: filteredToClasses.size
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
: {})
|
|
194
339
|
};
|
|
195
340
|
})());
|
|
196
341
|
}
|
package/dist/version-service.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { buildSuggestedCall } from "./build-suggested-call.js";
|
|
5
|
-
import { createError, ERROR_CODES } from "./errors.js";
|
|
5
|
+
import { createError, ERROR_CODES, isAppError } from "./errors.js";
|
|
6
6
|
import { computeFileSha1 } from "./hash.js";
|
|
7
7
|
import { defaultDownloadPath, downloadToCache } from "./repo-downloader.js";
|
|
8
8
|
const DEFAULT_VERSION_MANIFEST_URL = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json";
|
|
@@ -352,26 +352,48 @@ export class VersionService {
|
|
|
352
352
|
return details;
|
|
353
353
|
}
|
|
354
354
|
async fetchJson(url) {
|
|
355
|
-
const
|
|
356
|
-
|
|
355
|
+
const timeout = new AbortController();
|
|
356
|
+
const timer = setTimeout(() => timeout.abort(), this.config.fetchTimeoutMs);
|
|
357
|
+
try {
|
|
358
|
+
const response = await this.fetchFn(url, { signal: timeout.signal });
|
|
359
|
+
if (!response.ok) {
|
|
360
|
+
throw createError({
|
|
361
|
+
code: ERROR_CODES.REPO_FETCH_FAILED,
|
|
362
|
+
message: `Request failed for "${url}" with status ${response.status}.`,
|
|
363
|
+
details: {
|
|
364
|
+
url,
|
|
365
|
+
statusCode: response.status
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
try {
|
|
370
|
+
return await response.json();
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
throw createError({
|
|
374
|
+
code: ERROR_CODES.REPO_FETCH_FAILED,
|
|
375
|
+
message: `Response from "${url}" is not valid JSON.`,
|
|
376
|
+
details: { url }
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
// A typed status/JSON error is more precise than the timeout mapping even
|
|
382
|
+
// when the abort timer fired concurrently — never rewrite it.
|
|
383
|
+
if (isAppError(error) || !timeout.signal.aborted) {
|
|
384
|
+
throw error;
|
|
385
|
+
}
|
|
357
386
|
throw createError({
|
|
358
387
|
code: ERROR_CODES.REPO_FETCH_FAILED,
|
|
359
|
-
message: `Request
|
|
388
|
+
message: `Request timed out for "${url}" after ${this.config.fetchTimeoutMs}ms.`,
|
|
360
389
|
details: {
|
|
361
390
|
url,
|
|
362
|
-
|
|
391
|
+
timeoutMs: this.config.fetchTimeoutMs
|
|
363
392
|
}
|
|
364
393
|
});
|
|
365
394
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
catch {
|
|
370
|
-
throw createError({
|
|
371
|
-
code: ERROR_CODES.REPO_FETCH_FAILED,
|
|
372
|
-
message: `Response from "${url}" is not valid JSON.`,
|
|
373
|
-
details: { url }
|
|
374
|
-
});
|
|
395
|
+
finally {
|
|
396
|
+
clearTimeout(timer);
|
|
375
397
|
}
|
|
376
398
|
}
|
|
377
399
|
cacheIndexPath() {
|
package/dist/warning-details.js
CHANGED
|
@@ -31,7 +31,24 @@ const WARNING_RULES = [
|
|
|
31
31
|
affectedFields: ["mapping", "version"]
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
|
|
34
|
+
// compare-versions: the filter is fine but matched nothing, which used to
|
|
35
|
+
// be indistinguishable from "nothing changed".
|
|
36
|
+
test: /packageFilter ".*" matched no class/i,
|
|
37
|
+
code: "filter_matched_nothing",
|
|
38
|
+
category: "validation",
|
|
39
|
+
severity: "warning",
|
|
40
|
+
affectedFields: ["packageFilter"]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
// compare-versions could not lift the jars out of the obfuscated namespace.
|
|
44
|
+
test: /compared in the OBFUSCATED namespace/i,
|
|
45
|
+
code: "namespace_fallback",
|
|
46
|
+
category: "mapping",
|
|
47
|
+
severity: "warning",
|
|
48
|
+
affectedFields: ["packageFilter"]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
test: /falling back to vanilla|resolution failed; falling back|sources jar\.?\s*Falling back|(?:does not include|excludes) net\.minecraft/i,
|
|
35
52
|
code: "partial_coverage",
|
|
36
53
|
category: "coverage",
|
|
37
54
|
severity: "warning",
|
package/docs/README-ja.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@adhisang/minecraft-modding-mcp)
|
|
4
4
|
[](../LICENSE)
|
|
5
|
-
[](https://nodejs.org/)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
6
|
[](https://github.com/adhi-jp/minecraft-modding-mcp/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
8
|
**[English](../README.md)** | 日本語
|
|
@@ -33,7 +33,7 @@ stdio で動作し、Claude Desktop、Claude Code、VS Code、Codex CLI、Gemini
|
|
|
33
33
|
|
|
34
34
|
要件:
|
|
35
35
|
|
|
36
|
-
- Node.js 22+
|
|
36
|
+
- Node.js 22.13.0+
|
|
37
37
|
- Java は `remap-mod-jar` と、Vineflower または tiny-remapper を必要とするデコンパイル / リマップ処理でのみ必要です
|
|
38
38
|
|
|
39
39
|
ローカルでサーバーを起動:
|
|
@@ -64,6 +64,8 @@ codex mcp add minecraft-modding -- npx -y @adhisang/minecraft-modding-mcp
|
|
|
64
64
|
|
|
65
65
|
stdio トランスポートは、改行区切り形式と `Content-Length` フレーミングの両方を自動判別します。そのため、Codex と標準的な MCP クライアントで同じサーバー起動コマンドを利用できます。
|
|
66
66
|
|
|
67
|
+
サーバーは MCP プロトコルリビジョン `2026-07-28`(`server/discover` とリクエスト単位 `_meta` によるステートレス動作)と、従来の `initialize` ベースのレガシープロトコル(`2025-11-25`〜`2024-10-07`)の両方を同一バイナリでサポートします。1 プロセスはクライアントの最初のシグナルで選択された era を提供します。ワイヤレベルの詳細は [docs/tool-reference.md → MCP Protocol Support](tool-reference.md#mcp-protocol-support) を参照してください。
|
|
68
|
+
|
|
67
69
|
#### Claude Desktop
|
|
68
70
|
|
|
69
71
|
`claude_desktop_config.json` に次を追加します:
|
|
@@ -378,7 +380,7 @@ Mixin ソース、Access Widener ファイル、Forge / NeoForge の Access Tran
|
|
|
378
380
|
|
|
379
381
|
リポジトリ要件:
|
|
380
382
|
|
|
381
|
-
- Node.js 22+
|
|
383
|
+
- Node.js 22.13.0+
|
|
382
384
|
- `pnpm`
|
|
383
385
|
- ローカルでリマップやデコンパイルを実行する場合は Java
|
|
384
386
|
|
|
@@ -405,12 +407,16 @@ pnpm test
|
|
|
405
407
|
|
|
406
408
|
必要に応じて実行:
|
|
407
409
|
|
|
410
|
+
- `pnpm test:file <path...>`: 通常テストをファイル指定で絞り込む場合
|
|
411
|
+
- `pnpm test:grep <name-pattern>`: 通常テストを再帰的に集め、テスト名で絞り込む場合
|
|
408
412
|
- `pnpm test:manual:stdio-smoke`: MCP トランスポート、登録、手動ワークフローの変更時
|
|
409
413
|
- `pnpm test:manual:package-smoke`: パッケージインストールや配布形態の検証時
|
|
410
414
|
- `pnpm test:perf`: 検索、インデックス、性能に影響する変更時
|
|
411
415
|
- `pnpm test:coverage` または `pnpm test:coverage:lcov`: カバレッジ確認時(`lines=80`, `branches=70`, `functions=80`)
|
|
412
416
|
- `pnpm validate`: ローカルの完全検証スイートを実行する場合
|
|
413
417
|
|
|
418
|
+
通常の `.test.ts` ファイルは `tests/` 配下のドメイン別ディレクトリ(例: `source-service/`, `entry-tools/`, `mapping/`, `mixin/`, `integration/mcp-tools/`, `contracts/`, `utils/`)に置きます。ヘルパー専用モジュールは `tests/helpers` に残し、手動 smoke、性能、リソース、smoke 専用ファイルは既存の専用ディレクトリに残します。
|
|
419
|
+
|
|
414
420
|
## ライセンス
|
|
415
421
|
|
|
416
422
|
[MIT](../LICENSE)
|