@adhisang/minecraft-modding-mcp 4.2.1 → 6.0.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 +69 -0
- package/README.md +5 -4
- package/dist/access-transformer-parser.d.ts +2 -1
- package/dist/access-transformer-parser.js +10 -1
- package/dist/access-widener-parser.d.ts +1 -0
- package/dist/access-widener-parser.js +6 -3
- package/dist/build-suggested-call.js +31 -10
- package/dist/cache-registry.d.ts +8 -0
- package/dist/cache-registry.js +50 -32
- package/dist/config.d.ts +1 -0
- package/dist/config.js +4 -0
- package/dist/decompiler/vineflower.js +8 -2
- package/dist/entry-tools/analyze-mod-service.d.ts +24 -24
- package/dist/entry-tools/analyze-mod-service.js +2 -1
- package/dist/entry-tools/analyze-symbol-service.d.ts +57 -22
- package/dist/entry-tools/analyze-symbol-service.js +139 -34
- package/dist/entry-tools/batch-class-members-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-members-service.js +6 -6
- package/dist/entry-tools/batch-class-source-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-source-service.js +5 -6
- package/dist/entry-tools/batch-mappings-service.d.ts +3 -1
- package/dist/entry-tools/batch-mappings-service.js +4 -5
- package/dist/entry-tools/batch-symbol-exists-service.d.ts +3 -1
- package/dist/entry-tools/batch-symbol-exists-service.js +4 -5
- package/dist/entry-tools/compare-minecraft-service.d.ts +10 -10
- package/dist/entry-tools/compare-minecraft-service.js +1 -1
- package/dist/entry-tools/entry-tool-schema.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +1 -3
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +4 -3
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +0 -5
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/file.js +26 -2
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +8 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.js +13 -2
- package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/versions.js +3 -2
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +90 -89
- package/dist/entry-tools/inspect-minecraft/internal.js +32 -14
- package/dist/entry-tools/inspect-minecraft-service.d.ts +218 -218
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/entry-tools/response-contract.d.ts +3 -1
- package/dist/entry-tools/response-contract.js +3 -2
- package/dist/entry-tools/validate-project/cases/mixin.js +2 -1
- package/dist/entry-tools/validate-project/cases/project-summary.js +5 -3
- package/dist/entry-tools/validate-project-service.d.ts +42 -36
- package/dist/entry-tools/validate-project-service.js +3 -1
- package/dist/entry-tools/verify-mixin-target-service.d.ts +30 -0
- package/dist/entry-tools/verify-mixin-target-service.js +120 -29
- package/dist/error-mapping.d.ts +51 -0
- package/dist/error-mapping.js +157 -2
- package/dist/index.js +147 -76
- package/dist/java-process.js +1 -1
- package/dist/json-rpc-framing.d.ts +4 -0
- package/dist/json-rpc-framing.js +23 -1
- package/dist/mapping/internal-types.d.ts +24 -0
- package/dist/mapping/loaders/tiny-maven.js +46 -20
- package/dist/mapping/lookup.d.ts +13 -2
- package/dist/mapping/lookup.js +60 -2
- package/dist/mapping/types.d.ts +6 -0
- package/dist/mapping-service.d.ts +26 -2
- package/dist/mapping-service.js +212 -55
- package/dist/mcp-helpers.d.ts +1 -0
- package/dist/mcp-helpers.js +25 -3
- package/dist/minecraft-explorer-service.js +24 -11
- package/dist/mixin/access-validators.js +33 -1
- package/dist/mixin/annotation-validators.js +73 -9
- package/dist/mixin/parsed-validator.js +3 -2
- package/dist/mixin-parser.js +119 -7
- package/dist/mod-decompile-service.d.ts +2 -0
- package/dist/mod-decompile-service.js +21 -3
- package/dist/mod-remap-service.d.ts +20 -1
- package/dist/mod-remap-service.js +101 -45
- package/dist/mojang-tiny-mapping-service.js +5 -2
- package/dist/nbt/java-nbt-codec.js +46 -16
- package/dist/nbt/json-patch.js +51 -12
- package/dist/nbt/typed-json.d.ts +1 -0
- package/dist/nbt/typed-json.js +12 -2
- package/dist/nbt/types.d.ts +2 -2
- package/dist/observability.d.ts +6 -0
- package/dist/observability.js +10 -0
- package/dist/page-cursor.d.ts +17 -0
- package/dist/page-cursor.js +0 -0
- package/dist/path-converter.js +10 -3
- package/dist/registry-service.d.ts +2 -0
- package/dist/registry-service.js +41 -2
- package/dist/repo-downloader.js +4 -3
- package/dist/resources.js +45 -9
- package/dist/response-utils.d.ts +29 -4
- package/dist/response-utils.js +95 -5
- package/dist/source/access-validate.js +12 -2
- package/dist/source/artifact-resolver.js +2 -2
- package/dist/source/class-source/members-builder.d.ts +44 -1
- package/dist/source/class-source/members-builder.js +51 -4
- package/dist/source/class-source/snippet-builder.d.ts +13 -0
- package/dist/source/class-source/snippet-builder.js +54 -4
- package/dist/source/class-source-helpers.d.ts +4 -4
- package/dist/source/class-source-helpers.js +77 -20
- package/dist/source/class-source.d.ts +19 -0
- package/dist/source/class-source.js +144 -40
- package/dist/source/file-access.js +3 -2
- package/dist/source/indexer.js +29 -9
- package/dist/source/lifecycle/mapping-helpers.js +28 -3
- package/dist/source/lifecycle/runtime-check.js +20 -6
- package/dist/source/search.d.ts +1 -1
- package/dist/source/search.js +117 -30
- package/dist/source/validate-mixin/pipeline/resolve.js +23 -3
- package/dist/source/validate-mixin.d.ts +2 -1
- package/dist/source/validate-mixin.js +45 -4
- package/dist/source/workspace-target.js +17 -10
- package/dist/source-jar-reader.d.ts +54 -1
- package/dist/source-jar-reader.js +121 -10
- package/dist/source-resolver.js +2 -2
- package/dist/source-service.d.ts +28 -7
- package/dist/source-service.js +9 -1
- package/dist/stdio-supervisor.d.ts +2 -2
- package/dist/stdio-supervisor.js +29 -9
- package/dist/storage/db.js +24 -1
- package/dist/storage/files-repo.d.ts +15 -0
- package/dist/storage/files-repo.js +67 -37
- package/dist/storage/symbols-repo.d.ts +15 -0
- package/dist/storage/symbols-repo.js +53 -19
- package/dist/symbols/symbol-extractor.js +35 -6
- package/dist/text-truncate.d.ts +7 -0
- package/dist/text-truncate.js +21 -0
- package/dist/tiny-remapper-resolver.js +10 -0
- package/dist/tool-contract-manifest.js +2 -2
- package/dist/tool-execution-gate.js +12 -1
- package/dist/tool-guidance.d.ts +6 -2
- package/dist/tool-guidance.js +63 -13
- package/dist/tool-schemas.d.ts +561 -496
- package/dist/tool-schemas.js +175 -139
- package/dist/types.d.ts +1 -0
- package/dist/version-diff-service.js +5 -0
- package/dist/version-service.d.ts +3 -0
- package/dist/version-service.js +18 -2
- package/dist/warning-details.d.ts +30 -0
- package/dist/warning-details.js +80 -0
- package/dist/workspace-mapping-service.js +9 -0
- package/docs/README-ja.md +2 -2
- package/docs/examples.md +26 -2
- package/docs/tool-reference.md +22 -17
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -145,6 +145,11 @@ export class VersionDiffService {
|
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
const warnings = [];
|
|
148
|
+
if (input.maxClassResults != null &&
|
|
149
|
+
Number.isFinite(input.maxClassResults) &&
|
|
150
|
+
input.maxClassResults > MAX_CLASS_RESULTS_LIMIT) {
|
|
151
|
+
warnings.push(`maxClassResults was clamped to ${MAX_CLASS_RESULTS_LIMIT} from ${input.maxClassResults}.`);
|
|
152
|
+
}
|
|
148
153
|
const startedAt = Date.now();
|
|
149
154
|
log("info", "version-diff.start", { fromVersion, toVersion, category });
|
|
150
155
|
const includeClasses = category === "classes" || category === "all";
|
|
@@ -16,6 +16,7 @@ export type ListVersionsOutput = {
|
|
|
16
16
|
snapshots?: VersionEntry[];
|
|
17
17
|
cached: string[];
|
|
18
18
|
totalAvailable: number;
|
|
19
|
+
warnings?: string[];
|
|
19
20
|
};
|
|
20
21
|
export type ResolvedVersionJar = {
|
|
21
22
|
version: string;
|
|
@@ -47,6 +48,7 @@ export declare class VersionService {
|
|
|
47
48
|
private manifestCache;
|
|
48
49
|
private readonly versionDetailCache;
|
|
49
50
|
private readonly resolveLocks;
|
|
51
|
+
private indexWriteChain;
|
|
50
52
|
constructor(config: Config, fetchFn?: typeof fetch);
|
|
51
53
|
listVersions(input?: ListVersionsInput): Promise<ListVersionsOutput>;
|
|
52
54
|
listVersionIds(input?: ListVersionIdsInput): Promise<string[]>;
|
|
@@ -60,6 +62,7 @@ export declare class VersionService {
|
|
|
60
62
|
private cacheIndexPath;
|
|
61
63
|
private loadCacheIndex;
|
|
62
64
|
private recordCacheEntry;
|
|
65
|
+
private recordCacheEntryInternal;
|
|
63
66
|
private trimVersionDetailCache;
|
|
64
67
|
}
|
|
65
68
|
/**
|
package/dist/version-service.js
CHANGED
|
@@ -38,6 +38,9 @@ export class VersionService {
|
|
|
38
38
|
manifestCache;
|
|
39
39
|
versionDetailCache = new Map();
|
|
40
40
|
resolveLocks = new Map();
|
|
41
|
+
// Serializes index.json read-modify-write so parallel resolutions of different
|
|
42
|
+
// versions can't clobber each other (resolveLocks only guards the same version).
|
|
43
|
+
indexWriteChain = Promise.resolve();
|
|
41
44
|
constructor(config, fetchFn = globalThis.fetch) {
|
|
42
45
|
this.config = config;
|
|
43
46
|
this.fetchFn = fetchFn;
|
|
@@ -47,6 +50,10 @@ export class VersionService {
|
|
|
47
50
|
const manifest = await this.fetchManifest();
|
|
48
51
|
const includeSnapshots = input.includeSnapshots ?? false;
|
|
49
52
|
const limit = clampLimit(input.limit, 20, 200);
|
|
53
|
+
const warnings = [];
|
|
54
|
+
if (input.limit != null && Number.isFinite(input.limit) && input.limit > 200) {
|
|
55
|
+
warnings.push(`limit was clamped to 200 from ${input.limit}.`);
|
|
56
|
+
}
|
|
50
57
|
const versions = manifest.versions ?? [];
|
|
51
58
|
const releases = versions
|
|
52
59
|
.filter((entry) => entry.type === "release")
|
|
@@ -65,7 +72,8 @@ export class VersionService {
|
|
|
65
72
|
releases,
|
|
66
73
|
snapshots: includeSnapshots ? snapshots : undefined,
|
|
67
74
|
cached: Array.from(new Set(cached)).sort((a, b) => a.localeCompare(b)),
|
|
68
|
-
totalAvailable: versions.length
|
|
75
|
+
totalAvailable: versions.length,
|
|
76
|
+
...(warnings.length ? { warnings } : {})
|
|
69
77
|
};
|
|
70
78
|
}
|
|
71
79
|
async listVersionIds(input = {}) {
|
|
@@ -389,7 +397,15 @@ export class VersionService {
|
|
|
389
397
|
return { entries: [] };
|
|
390
398
|
}
|
|
391
399
|
}
|
|
392
|
-
|
|
400
|
+
recordCacheEntry(entry) {
|
|
401
|
+
// Chain onto the previous write so reads and writes never interleave. The
|
|
402
|
+
// caller still awaits its own write's result, but the shared chain swallows
|
|
403
|
+
// failures so one rejected write cannot poison subsequent writes.
|
|
404
|
+
const next = this.indexWriteChain.then(() => this.recordCacheEntryInternal(entry));
|
|
405
|
+
this.indexWriteChain = next.catch(() => undefined);
|
|
406
|
+
return next;
|
|
407
|
+
}
|
|
408
|
+
async recordCacheEntryInternal(entry) {
|
|
393
409
|
const indexPath = this.cacheIndexPath();
|
|
394
410
|
const existing = await this.loadCacheIndex();
|
|
395
411
|
const deduped = existing.entries.filter((candidate) => candidate.version !== entry.version);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type WarningCategory = "pagination" | "mapping" | "coverage" | "validation" | "general";
|
|
2
|
+
export type WarningSeverity = "warning" | "info";
|
|
3
|
+
export type WarningDetail = {
|
|
4
|
+
/** Stable machine code for the warning family. */
|
|
5
|
+
code: string;
|
|
6
|
+
category: WarningCategory;
|
|
7
|
+
severity: WarningSeverity;
|
|
8
|
+
/** Index into `meta.warnings[]` that holds the original human-readable text. */
|
|
9
|
+
index: number;
|
|
10
|
+
/** Input fields a caller can adjust to address the warning, when applicable. */
|
|
11
|
+
affectedFields?: string[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Build the structured `warningDetails[]` companion for a list of warning strings.
|
|
15
|
+
* The mapping is 1:1 and order-preserving, so each entry's `index` equals its
|
|
16
|
+
* position and dereferences the text via `warnings[index]`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function classifyWarnings(warnings: string[]): WarningDetail[];
|
|
19
|
+
/**
|
|
20
|
+
* Cap of structured warningDetails entries emitted at `detail:"summary"`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const SUMMARY_WARNING_DETAIL_CAP = 5;
|
|
23
|
+
/**
|
|
24
|
+
* At `detail:"summary"` the structured warningDetails companion is capped to a small
|
|
25
|
+
* representative set to keep responses lean. The full human-readable text still lives
|
|
26
|
+
* in `meta.warnings[]`, and each kept entry's `index` continues to dereference it, so
|
|
27
|
+
* no information is lost — only the redundant structured duplicate is trimmed. Standard
|
|
28
|
+
* and full detail return the companion unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export declare function capWarningDetailsForSummary(warningDetails: WarningDetail[], isSummary: boolean): WarningDetail[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Structured companion to the string `meta.warnings`. Each warning string is
|
|
2
|
+
// classified into a high-value family so agents can branch on category/severity
|
|
3
|
+
// without parsing prose. The original text is NOT duplicated here; each entry
|
|
4
|
+
// references its warning by position via `index` (read `meta.warnings[index]`).
|
|
5
|
+
// First matching rule wins; more specific patterns precede broader ones.
|
|
6
|
+
const WARNING_RULES = [
|
|
7
|
+
{
|
|
8
|
+
test: /Member list was truncated|truncated to \d+ (entries|rows)|Raise maxCandidates|Raise maxRows/i,
|
|
9
|
+
code: "result_truncated",
|
|
10
|
+
category: "pagination",
|
|
11
|
+
severity: "info",
|
|
12
|
+
affectedFields: ["maxMembers", "maxRows", "maxCandidates", "cursor"]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
test: /\bwas clamped to\b/i,
|
|
16
|
+
code: "input_clamped",
|
|
17
|
+
category: "validation",
|
|
18
|
+
severity: "info"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
test: /are not indexed|non-Java resources are not indexed/i,
|
|
22
|
+
code: "resource_not_indexed",
|
|
23
|
+
category: "coverage",
|
|
24
|
+
severity: "info"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
test: /namespace translation requires a version|could not be applied because the artifact has no version|Could not (re)?map .* (from .* to|to .* namespace)|Remap failed for|Mapping lookup failed|No exact class symbol matched|Unsupported .* namespace/i,
|
|
28
|
+
code: "namespace_fallback",
|
|
29
|
+
category: "mapping",
|
|
30
|
+
severity: "warning",
|
|
31
|
+
affectedFields: ["mapping", "version"]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
test: /falling back to vanilla|resolution failed; falling back|sources jar\.?\s*Falling back|does not include net\.minecraft/i,
|
|
35
|
+
code: "partial_coverage",
|
|
36
|
+
category: "coverage",
|
|
37
|
+
severity: "warning",
|
|
38
|
+
affectedFields: ["scope"]
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
function classifyWarning(message, index) {
|
|
42
|
+
for (const rule of WARNING_RULES) {
|
|
43
|
+
if (rule.test.test(message)) {
|
|
44
|
+
return {
|
|
45
|
+
code: rule.code,
|
|
46
|
+
category: rule.category,
|
|
47
|
+
severity: rule.severity,
|
|
48
|
+
index,
|
|
49
|
+
...(rule.affectedFields ? { affectedFields: rule.affectedFields } : {})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { code: "general", category: "general", severity: "info", index };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the structured `warningDetails[]` companion for a list of warning strings.
|
|
57
|
+
* The mapping is 1:1 and order-preserving, so each entry's `index` equals its
|
|
58
|
+
* position and dereferences the text via `warnings[index]`.
|
|
59
|
+
*/
|
|
60
|
+
export function classifyWarnings(warnings) {
|
|
61
|
+
return warnings.map((message, index) => classifyWarning(message, index));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cap of structured warningDetails entries emitted at `detail:"summary"`.
|
|
65
|
+
*/
|
|
66
|
+
export const SUMMARY_WARNING_DETAIL_CAP = 5;
|
|
67
|
+
/**
|
|
68
|
+
* At `detail:"summary"` the structured warningDetails companion is capped to a small
|
|
69
|
+
* representative set to keep responses lean. The full human-readable text still lives
|
|
70
|
+
* in `meta.warnings[]`, and each kept entry's `index` continues to dereference it, so
|
|
71
|
+
* no information is lost — only the redundant structured duplicate is trimmed. Standard
|
|
72
|
+
* and full detail return the companion unchanged.
|
|
73
|
+
*/
|
|
74
|
+
export function capWarningDetailsForSummary(warningDetails, isSummary) {
|
|
75
|
+
if (!isSummary || warningDetails.length <= SUMMARY_WARNING_DETAIL_CAP) {
|
|
76
|
+
return warningDetails;
|
|
77
|
+
}
|
|
78
|
+
return warningDetails.slice(0, SUMMARY_WARNING_DETAIL_CAP);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=warning-details.js.map
|
|
@@ -65,6 +65,15 @@ function buildDependencyPropertyKeys(group, name) {
|
|
|
65
65
|
`${groupSegment}_${name}_version`,
|
|
66
66
|
`${camelGroupName}Version`
|
|
67
67
|
];
|
|
68
|
+
// Umbrella fallback: submodules of an umbrella package (e.g. Fabric API's
|
|
69
|
+
// net.fabricmc.fabric-api:fabric-screen-handler-api-v1) rarely declare their own
|
|
70
|
+
// version — the parent declares a single umbrella property (fabric_api_version /
|
|
71
|
+
// fabricApiVersion) that all submodules inherit. When the artifact name differs from
|
|
72
|
+
// the group's last segment, append the umbrella's keys as LOWER-priority candidates so
|
|
73
|
+
// submodule version detection no longer fails with ERR_DEPENDENCY_VERSION_UNRESOLVED.
|
|
74
|
+
if (groupSegment !== name) {
|
|
75
|
+
keys.push(`${groupSegment.replace(/-/g, "_")}_version`, `${camelCaseDependencyName(groupSegment)}Version`);
|
|
76
|
+
}
|
|
68
77
|
const seen = new Set();
|
|
69
78
|
const deduped = [];
|
|
70
79
|
for (const key of keys) {
|
package/docs/README-ja.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
stdio で動作し、Claude Desktop、Claude Code、VS Code、Codex CLI、Gemini CLI などの MCP 対応クライアントから利用できます。
|
|
17
17
|
|
|
18
|
-
**
|
|
18
|
+
**41 ツール**(6 エントリー + 35 エキスパート) | **9 リソース** | **4 マッピング名前空間** | **SQLite ベースのキャッシュ**
|
|
19
19
|
|
|
20
20
|
## 特長
|
|
21
21
|
|
|
@@ -301,7 +301,7 @@ Minecraft バージョン間でのクラス / レジストリ変更比較と、
|
|
|
301
301
|
| ツール | 役割 |
|
|
302
302
|
| --- | --- |
|
|
303
303
|
| `find-mapping` | クラス、フィールド、メソッドのシンボルに対するマッピング候補を調べる |
|
|
304
|
-
| `resolve-method-mapping-exact` | owner
|
|
304
|
+
| `resolve-method-mapping-exact` | `find-mapping`(kind=method, signatureMode=exact)の厳密版ショートカット。owner+name+descriptor の三つ組が必須 |
|
|
305
305
|
| `get-class-api-matrix` | 1 つのクラス API を `obfuscated`、`mojang`、`intermediary`、`yarn` で見比べる |
|
|
306
306
|
| `resolve-workspace-symbol` | Gradle ワークスペースからコンパイル時に見えるシンボル名を解決する |
|
|
307
307
|
| `check-symbol-exists` | 名前空間内でクラス、フィールド、メソッドが存在するかを確認する |
|
package/docs/examples.md
CHANGED
|
@@ -105,7 +105,7 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
105
105
|
"tool": "get-class-source",
|
|
106
106
|
"arguments": {
|
|
107
107
|
"target": {
|
|
108
|
-
"
|
|
108
|
+
"kind": "artifact",
|
|
109
109
|
"artifactId": "<artifact-id>"
|
|
110
110
|
},
|
|
111
111
|
"className": "net.minecraft.server.Main",
|
|
@@ -137,7 +137,7 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
137
137
|
"tool": "get-class-members",
|
|
138
138
|
"arguments": {
|
|
139
139
|
"target": {
|
|
140
|
-
"
|
|
140
|
+
"kind": "artifact",
|
|
141
141
|
"artifactId": "<artifact-id>"
|
|
142
142
|
},
|
|
143
143
|
"className": "net.minecraft.server.Main",
|
|
@@ -395,6 +395,30 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
395
395
|
|
|
396
396
|
If the input JAR was already built with Mojang mappings, use `targetMapping: "mojang"` to get a copied output JAR and a `fromMapping: "mojang"` result.
|
|
397
397
|
|
|
398
|
+
### Bridge a mod hit to a Minecraft-side check
|
|
399
|
+
|
|
400
|
+
When `search-mod-source` or `get-mod-class-source` surfaces a class or member that
|
|
401
|
+
looks like a Minecraft target (for example a Mixin `@Shadow`/`@Inject` target, or a
|
|
402
|
+
symbol from a crash stack), verify it against the target Minecraft version before
|
|
403
|
+
trusting it. Feed the owner/member into `verify-mixin-target`. When your owner/member
|
|
404
|
+
are in a readable namespace (e.g. `mojang`/`yarn`) but the resolved artifact is
|
|
405
|
+
obfuscated, set `autoRemap: true` to translate them automatically in one call:
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"tool": "verify-mixin-target",
|
|
410
|
+
"arguments": {
|
|
411
|
+
"target": { "kind": "version", "value": "1.21.10" },
|
|
412
|
+
"owner": "net.minecraft.world.entity.LivingEntity",
|
|
413
|
+
"member": { "kind": "method", "name": "tickServer", "descriptor": "()V" },
|
|
414
|
+
"mapping": "mojang",
|
|
415
|
+
"autoRemap": true
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
For a plain "does this symbol exist in this version?" question, use `analyze-symbol task="exists"` instead.
|
|
421
|
+
|
|
398
422
|
## Validation
|
|
399
423
|
|
|
400
424
|
### Validate Mixin source
|
package/docs/tool-reference.md
CHANGED
|
@@ -23,15 +23,15 @@ Start here when you are not sure which tool to reach for. In every row, the left
|
|
|
23
23
|
| "Does this Mixin target the right class and descriptor?" | `validate-mixin` (works standalone with `version=1.21.10`; provide inline source, a path, or a mixin config). |
|
|
24
24
|
| "Validate every Mixin / Access Widener / Access Transformer in a workspace." | `validate-project` (`task="project-summary"` discovers everything; `task="mixin"|"access-widener"|"access-transformer"` validates a single subject). |
|
|
25
25
|
| "Inspect the Minecraft workspace or an artifact without picking a lower-level tool." | `inspect-minecraft` — use this when you want the server to resolve the artifact and pick the right sub-tool. |
|
|
26
|
-
| "Trace when a symbol was added, renamed, or removed across versions." | `trace-symbol-lifecycle` (or `analyze-symbol task="lifecycle"
|
|
27
|
-
| "Compare two MC versions or two class versions." | `compare-minecraft` (`task="class"` for a single class diff; `task="versions"` for a full summary). |
|
|
26
|
+
| "Trace when a symbol was added, renamed, or removed across versions." | `trace-symbol-lifecycle` (or `analyze-symbol task="lifecycle"`, which now exposes `fromVersion`/`toVersion`/`maxVersions`/`includeTimeline`). |
|
|
27
|
+
| "Compare two MC versions or two class versions." | `compare-minecraft` (`task="class-diff"` for a single class diff; `task="versions"` for a full summary). |
|
|
28
28
|
| "Inspect or remap an existing `.jar` file." | `analyze-mod` / `analyze-mod-jar` / `remap-mod-jar`. |
|
|
29
29
|
|
|
30
30
|
## Essential Conventions
|
|
31
31
|
|
|
32
32
|
- Start with the top-level workflow tools when possible. `inspect-minecraft`, `analyze-symbol`, `compare-minecraft`, `analyze-mod`, `validate-project`, and `manage-cache` cover the common workflows and return summary-first results with follow-up hints.
|
|
33
33
|
- `resolve-artifact` uses `target: { kind, value }`. `kind` is one of `"version"`, `"jar"`, `"coordinate"`, `"workspace"`, or `"dependency"` (see "Workspace and dependency target shapes" below).
|
|
34
|
-
- `get-class-source` and `get-class-members` use `target: {
|
|
34
|
+
- `get-class-source` and `get-class-members` use `target: { kind, value }` — the same `kind`-based shape as `resolve-artifact` (`"version"`, `"jar"`, `"coordinate"`, `"workspace"`, `"dependency"`), plus `target: { kind: "artifact", artifactId }` to reuse an already-resolved artifact.
|
|
35
35
|
- `find-class`, `search-class-source`, `list-artifact-files`, and `find-mapping` keep their existing input shapes (an `artifactId` or a `version`); they do not currently accept `target.kind="workspace"` or `target.kind="dependency"`.
|
|
36
36
|
- `validate-mixin` and `validate-project task="mixin"` use `input.mode="inline" | "path" | "paths" | "config" | "project"`.
|
|
37
37
|
- Positive integer tool arguments accept numeric strings such as `"10"` for documented top-level parameters.
|
|
@@ -46,12 +46,14 @@ Start here when you are not sure which tool to reach for. In every row, the left
|
|
|
46
46
|
| --- | --- | --- |
|
|
47
47
|
| `"ok"` | `counts.total > 0`, OR `counts.total === 0` AND binary extraction succeeded AND `decompiledFallback` did not fire (genuinely empty class). | none |
|
|
48
48
|
| `"partial"` | `decompiledFallback` is populated (bytecode returned zero but the indexed decompiled source supplied member names; `qualityFlags` includes `"members-from-decompiled-source"`). | `decompiledFallback`, `decompiledMemberCounts` |
|
|
49
|
-
| `"members_unavailable"` | Binary signature extraction threw a non-`ERR_CLASS_NOT_FOUND` error AND no decompiled fallback was available. | `unavailableReason: string`, `suggestedCall: { tool: "get-class-source", params: { target: {
|
|
49
|
+
| `"members_unavailable"` | Binary signature extraction threw a non-`ERR_CLASS_NOT_FOUND` error AND no decompiled fallback was available. | `unavailableReason: string`, `suggestedCall: { tool: "get-class-source", params: { target: { kind: "artifact", artifactId }, className, mode: "snippet", mapping } }` (the params validate against `get-class-source`'s input schema). |
|
|
50
50
|
|
|
51
51
|
The shape is purely additive: `members` / `counts` / `decompiledFallback` / `decompiledMemberCounts` / `qualityFlags` are unchanged for callers that ignore `status`. `ERR_CLASS_NOT_FOUND` still propagates as a thrown error rather than as `members_unavailable`. Set `MEMBERS_STATUS_LEGACY=1` at process start to omit `status` / `unavailableReason` / `suggestedCall` entirely (legacy shape).
|
|
52
52
|
- `search-class-source` accepts `queryNamespace`. When set and the artifact's `mappingApplied` differs, `intent="symbol"` queries for fully-qualified class names are translated through `find-mapping` (source=`queryNamespace`, target=artifact namespace) before the indexed search runs; the response carries a `translatedQuery` block describing the rewrite. `intent="text"` / `intent="path"` do not translate — text search is a literal match against the artifact namespace; the response surfaces a `warnings` array instead. `sourcePriority` is only consulted during translation.
|
|
53
|
-
-
|
|
54
|
-
-
|
|
53
|
+
- All expert and batch tools share the entry-tool **`detail`** (`summary` | `standard` | `full`) + **`include[]`** response contract (the per-tool `compact` boolean is gone). `summary` is the terse shape (drops diagnostics/empties, slims candidates), `standard` keeps fields but drops heavy diagnostics, `full` keeps everything. Per-tool defaults are chosen so the default response is unchanged: `resolve-artifact`, `find-mapping`, `resolve-method-mapping-exact`, `resolve-workspace-symbol`, `check-symbol-exists`, and the four `batch-*` tools default **`summary`**; `get-class-source`, `get-class-members`, `search-class-source`, and `list-artifact-files` default **`standard`**. (Migration: `compact: true` → `detail: "summary"`; `compact: false` → `detail: "full"`.)
|
|
54
|
+
- At `detail: "summary"`, empty arrays / null / empty objects are stripped. For `resolve-artifact` it also omits `provenance`, `artifactContents`, `sampleEntries`, `adjacentSourceCandidates`, `binaryJarPath`, `coordinate`, `repoUrl`, and `resolvedSourceJarPath` — `include: ["provenance"|"artifact"|"samples"|"candidates"|"paths"]` re-adds the matching field(s). For mapping tools, `summary` (1) omits the redundant `candidates` array on a single full-confidence exact-match resolution and (2) slims the tail to `{kind, symbol, owner, name, descriptor, confidence, matchKind}` with `candidateDetailsTruncated: true` when an unresolved result has more than three candidates; `include: ["candidates"]` keeps the full candidate list. `candidatesTruncated` keeps its independent meaning ("more candidates exist upstream than returned").
|
|
55
|
+
- `get-class-source` and `get-class-members` omit the diagnostic fields `provenance`, `artifactContents`, and `qualityFlags` at `detail: "summary"` and `detail: "standard"` (the lean common path). Pass `include: ["provenance"]` (or the legacy alias `includeProvenance: true`) or use `detail: "full"` to include all three. `detail: "summary"` additionally strips empty fields, and for `get-class-members` also strips `context`; `decompiledFallback` and `decompiledMemberCounts` are preserved. `search-class-source` and `list-artifact-files` omit `artifactContents` at `detail: "summary"` (re-add via `include: ["artifact"]`) — the primary `hits` / `items` payload is always preserved.
|
|
56
|
+
- `get-class-members` returns a slim member shape: `accessFlags` is dropped (modifiers are in `javaSignature`), `ownerFqn` is hoisted to a single block-level `members.ownerFqn` when all members share one owner (per-member only when `includeInherited` surfaces multiple owners), and **field** `jvmDescriptor` is omitted by default. Method/constructor `jvmDescriptor` is always present for overload disambiguation. Pass `include: ["descriptors"]` (or the legacy alias `includeDescriptors: true`) to also emit field descriptors.
|
|
55
57
|
- Windows and WSL path forms are normalized for `jarPath`, `projectPath`, and environment-variable path overrides.
|
|
56
58
|
- Heavy analysis tools are serialized in-process to protect stdio stability. Queue overflow returns `ERR_LIMIT_EXCEEDED`.
|
|
57
59
|
- All tools and JSON resources use the standard `{ result?, error?, meta }` envelope. `class-source` and `artifact-file` resources return raw text on success and structured JSON on failure.
|
|
@@ -90,7 +92,7 @@ Workspace detection is memoised in a process-resident `WorkspaceContextCache` (1
|
|
|
90
92
|
- `remap-mod-jar` requires Java and supports Fabric/Quilt inputs. Mojang-mapped inputs can only be copied through `targetMapping="mojang"`.
|
|
91
93
|
- `search-mod-source` enforces `query.length <= 200` and `limit <= 200`.
|
|
92
94
|
- `get-registry-data` can return names and counts only with `includeData=false`, or clip detailed payloads with `maxEntriesPerRegistry`.
|
|
93
|
-
- `validate-mixin` summary-first
|
|
95
|
+
- `validate-mixin` defaults `reportMode="summary-first"`: it hoists shared provenance/warnings/incomplete reasons and drops per-result `resolvedMembers`/`toolHealth`/`structuredWarnings`. Pass `reportMode="full"` (or `explain=true`) to get per-result `resolvedMembers`/`toolHealth`/`resolutionTrace` back. For the leanest output combine `includeIssues=false`, `reportMode="compact"`, and `warningMode="aggregated"`.
|
|
94
96
|
- `validate-mixin` top-level failures expose `failedStage` as a first-class field on the serialized `error` envelope (alongside `code`, `hints`, `suggestedCall`) — one of `"input-validation" | "resolve" | "mapping-health" | "parse" | "target-lookup"`. Branch on that before inspecting `message` to recover automatically (e.g. retry `resolve` failures with `scope="vanilla"`, retry `target-lookup` failures with a different `mapping`). Nested errors that already carry a `failedStage` are preserved so upstream tags (e.g. from `resolve-artifact`) surface unchanged.
|
|
95
97
|
- `validate-mixin` per-result `quickSummary` appends `Scope fell back from "<requested>" to "<applied>" (<reason>).` when `provenance.scopeFallback` is set and `Mapping health degraded: <degradations>.` when `toolHealth.overallHealthy === false`. Clean validations keep the original one-line summary; the extra notes only attach when the pipeline actually fell back or detected a degraded mapping.
|
|
96
98
|
- `mapping-health` stays lightweight for `obfuscated` and `mojang` requests. It avoids full Tiny mapping graph loads unless the caller requests `intermediary` or `yarn`, where Tiny namespace availability is part of the health check.
|
|
@@ -148,7 +150,7 @@ Common input fields:
|
|
|
148
150
|
- `entries: Array<...>` — 1..50 per-entry payloads. Tool-specific shape (see each subsection).
|
|
149
151
|
- `concurrency: number` (1..8, default 4) — passed to the worker pool. Above 8 is rejected with `ERR_INVALID_INPUT` (`fieldErrors[0].path === "concurrency"`).
|
|
150
152
|
- `failFast: boolean` (default `false`) — when `true`, the first per-entry error sets an abort flag. Workers that have not yet picked up an entry short-circuit with `error.code === "ERR_BATCH_ABORTED"`. **In-flight workers continue to completion** — they are not cancelled (no AbortSignal wiring). Already-completed `ok` entries are still returned in `results`.
|
|
151
|
-
- `
|
|
153
|
+
- `detail: "summary" | "standard" | "full"` (default `summary`) + `include[]` — applies the same per-tool projection the corresponding single tool applies at that detail level to each entry's `result`. `detail: "summary"` matches the old `compact: true` per-entry shape; `detail: "full"` matches the old `compact: false` (byte-identical to the single tool's full output).
|
|
152
154
|
- Per-tool shared inputs (`target`, `mapping`, `projectPath`, `version`, etc.) follow the same shape as the matching single tool.
|
|
153
155
|
|
|
154
156
|
Resource behavior: `concurrency` limits per-entry dispatch for one batch call. Within one MCP server process, entries or calls that need the same artifact index or decompiled fallback share the in-flight rebuild by `artifactId`. Separate MCP server processes sharing the same cache are not coordinated by this process-local guard.
|
|
@@ -191,8 +193,8 @@ Per-entry retry semantics: each `error.suggestedCall` proposes the **matching si
|
|
|
191
193
|
|
|
192
194
|
| Batch tool | Single tool retry |
|
|
193
195
|
|---|---|
|
|
194
|
-
| `batch-class-source` | `get-class-source` (with `target: {
|
|
195
|
-
| `batch-class-members` | `get-class-members` (with `target: {
|
|
196
|
+
| `batch-class-source` | `get-class-source` (with `target: { kind: "artifact", artifactId: <shared> }`) |
|
|
197
|
+
| `batch-class-members` | `get-class-members` (with `target: { kind: "artifact", artifactId: <shared> }`) |
|
|
196
198
|
| `batch-symbol-exists` | `check-symbol-exists` (with `version` derived from the resolved artifact) |
|
|
197
199
|
| `batch-mappings` | `find-mapping` (with `version` carried from the top-level batch input) |
|
|
198
200
|
|
|
@@ -208,7 +210,7 @@ Read source for many classes against one shared resolved artifact. Per-entry: `{
|
|
|
208
210
|
|
|
209
211
|
### batch-class-members
|
|
210
212
|
|
|
211
|
-
List members for many classes against one shared resolved artifact. Per-entry: `{ className, access?, includeSynthetic?, includeInherited?, memberPattern?, maxMembers? }`. Shared inputs match `batch-class-source`. Result shape per entry mirrors `get-class-members`, including the `status` field (`"
|
|
213
|
+
List members for many classes against one shared resolved artifact. Per-entry: `{ className, access?, includeSynthetic?, includeInherited?, memberPattern?, maxMembers? }`. Shared inputs match `batch-class-source`. Result shape per entry mirrors `get-class-members`, including the `status` field (`"ok"` / `"partial"` / `"members_unavailable"`).
|
|
212
214
|
|
|
213
215
|
### batch-symbol-exists
|
|
214
216
|
|
|
@@ -265,7 +267,8 @@ These environment variables are read once at worker startup and provide rollback
|
|
|
265
267
|
|
|
266
268
|
- Start with `inspect-minecraft` for version, artifact, class, file, and search workflows before dropping to `list-versions`, `resolve-artifact`, `get-class-source`, `get-class-members`, `search-class-source`, `get-artifact-file`, or `list-artifact-files`.
|
|
267
269
|
- Start with `analyze-symbol` for symbol mapping, existence, lifecycle, workspace, and API overview workflows before using `find-mapping`, `resolve-method-mapping-exact`, `check-symbol-exists`, `trace-symbol-lifecycle`, `resolve-workspace-symbol`, or `get-class-api-matrix` directly.
|
|
268
|
-
- `analyze-symbol task="lifecycle"`
|
|
270
|
+
- `analyze-symbol task="lifecycle"` accepts `fromVersion`/`toVersion`/`maxVersions`/`includeTimeline`/`includeSnapshots` (lifecycle-only; rejected on other tasks). The legacy `version` field is a back-compat alias for `toVersion` (range end). The default scan window is the service default of 120 versions (max 400); pass `maxVersions: 5` for the old narrow window. Use `trace-symbol-lifecycle` directly only for parity with the expert tool.
|
|
271
|
+
- `analyze-symbol` `subject.kind` accepts `"symbol"` to auto-detect the concrete kind from the selector (owner+descriptor ⇒ method, owner only ⇒ field, otherwise ⇒ class); the inferred kind is surfaced as a warning. For `task="api-overview"` the inferred kind is always class.
|
|
269
272
|
- Start with `compare-minecraft` for version-pair, class diff, registry diff, and migration-summary flows before using `compare-versions`, `diff-class-signatures`, or `get-registry-data` directly.
|
|
270
273
|
- Start with `analyze-mod` for metadata-first mod inspection and safe remap preview/apply flows before using `analyze-mod-jar`, `decompile-mod-jar`, `get-mod-class-source`, `search-mod-source`, or `remap-mod-jar` directly.
|
|
271
274
|
- Start with `validate-project` for workspace summaries and direct Mixin, Access Widener, or Access Transformer validation before using `validate-mixin`, `validate-access-widener`, or `validate-access-transformer` directly.
|
|
@@ -289,7 +292,7 @@ These environment variables are read once at worker startup and provide rollback
|
|
|
289
292
|
- `validate-access-transformer` accepts `atNamespace="srg" | "mojang" | "obfuscated"`. When `projectPath` points at a Forge or NeoForge workspace, the tool can infer that namespace automatically and validate against loader/runtime artifacts for `scope="loader"`.
|
|
290
293
|
- Start with `manage-cache` for cache inventory and safe cleanup. Use `executionMode="preview"` before `executionMode="apply"`.
|
|
291
294
|
- Replace `resolve-artifact` `targetKind` and `targetValue` with `target: { kind, value }`.
|
|
292
|
-
- Replace `get-class-source` and `get-class-members` top-level `artifactId`, `targetKind`, and `targetValue` with `target: {
|
|
295
|
+
- Replace `get-class-source` and `get-class-members` top-level `artifactId`, `targetKind`, and `targetValue` with `target: { kind, value }` (same shape as `resolve-artifact`) or `target: { kind: "artifact", artifactId }`. The earlier `target: { type: "artifact", artifactId }` form is gone — use `{ kind: "artifact", artifactId }`; the redundant `{ type: "resolve", ... }` wrapper is still accepted but `type` is ignored.
|
|
293
296
|
- `resolve-method-mapping-exact` is method-only and no longer accepts `kind`.
|
|
294
297
|
- Replace `validate-mixin` `source`, `sourcePath`, `sourcePaths`, `mixinConfigPath`, and `sourceRoot` with `input.mode` plus `input.source`, `input.path`, `input.paths[]`, `input.configPaths[]`, and `sourceRoots[]`.
|
|
295
298
|
- `search-class-source` removed snippet, definition, and relation expansion. Responses now contain compact `hits[]` plus `nextCursor?`, and `symbolKind` is only valid with `intent="symbol"`.
|
|
@@ -309,13 +312,15 @@ MCP resources provide URI-based access to Minecraft data for clients that suppor
|
|
|
309
312
|
|
|
310
313
|
| Resource | URI Template | Description |
|
|
311
314
|
| --- | --- | --- |
|
|
312
|
-
| `class-source` | `mc://source/{artifactId}/{className}` | Java source code for a class within a resolved artifact |
|
|
315
|
+
| `class-source` | `mc://source/{artifactId}/{className}` | Java source code for a class within a resolved artifact (raw text). |
|
|
316
|
+
| `class-source-json` | `mc://source-json/{artifactId}/{className}` | Full class source plus metadata (`artifactId`, `mappingApplied`, `totalLines`, `returnedRange`, `provenance`, `warnings`) as a structured JSON envelope — easier to cite and continue than the raw-text `class-source`. |
|
|
313
317
|
| `artifact-file` | `mc://artifact/{artifactId}/files/{filePath}` | Raw content of a file within a resolved artifact |
|
|
314
|
-
| `find-mapping` | `mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{name}` | Look up a mapping between two naming namespaces |
|
|
318
|
+
| `find-mapping` | `mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{name}` | Look up a **class** mapping between two naming namespaces. The URI carries no `owner`, so use `find-member-mapping` (or the `find-mapping` tool) for field/method lookups. |
|
|
319
|
+
| `find-member-mapping` | `mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{owner}/{name}` | Look up a **field or method** mapping, including the `owner` class the member belongs to. For exact method overload resolution use the `find-mapping` tool with a `descriptor`. |
|
|
315
320
|
| `class-members` | `mc://artifact/{artifactId}/members/{className}` | List constructors, methods, and fields for a class |
|
|
316
321
|
| `artifact-metadata` | `mc://artifact/{artifactId}` | Metadata for a previously resolved artifact |
|
|
317
322
|
|
|
318
|
-
`versions-list`, `runtime-metrics`, `find-mapping`, `class-members`, and `artifact-metadata` return structured JSON envelopes on success (`{ result, meta }`) and failure (`{ error, meta }`).
|
|
323
|
+
`versions-list`, `runtime-metrics`, `find-mapping`, `find-member-mapping`, `class-source-json`, `class-members`, and `artifact-metadata` return structured JSON envelopes on success (`{ result, meta }`) and failure (`{ error, meta }`).
|
|
319
324
|
|
|
320
325
|
`class-source` and `artifact-file` keep raw text responses on success, but still return structured JSON errors on failure.
|
|
321
326
|
|
|
@@ -380,7 +385,7 @@ If `find-class` or `get-class-source` returns no hit on an `obfuscated` artifact
|
|
|
380
385
|
|
|
381
386
|
Method descriptor precision is best on Tiny-backed paths (`intermediary` and `yarn`). For `obfuscated <-> mojang`, Mojang `client_mappings` do not carry JVM descriptors, so descriptor queries may fall back to name matching and emit a warning.
|
|
382
387
|
|
|
383
|
-
Use `resolve-method-mapping-exact` when candidate ranking is not enough and the workflow needs strict `owner + name + descriptor` certainty.
|
|
388
|
+
Use `resolve-method-mapping-exact` when candidate ranking is not enough and the workflow needs strict `owner + name + descriptor` certainty. It is a strict shortcut for `find-mapping` (kind=method, signatureMode=exact) that additionally requires a **complete** descriptor projection — it returns `mapping_unavailable` when the descriptor's class references cannot all be projected to the target namespace, whereas `find-mapping`'s exact mode resolves those leniently. Prefer `find-mapping kind=method signatureMode=exact` unless you specifically need that strict-completeness guarantee.
|
|
384
389
|
|
|
385
390
|
Use `find-mapping` `disambiguation.ownerHint` and `disambiguation.descriptorHint` to narrow ambiguous candidate sets.
|
|
386
391
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhisang/minecraft-modding-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "MCP server for AI-assisted Minecraft modding: inspect decompiled source, resolve Mojang/Yarn/Intermediary mappings, diff versions, analyze Fabric/Forge/NeoForge mod JARs, and validate Mixin, Access Widener, and Access Transformer files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|