@adhisang/minecraft-modding-mcp 1.2.0 → 2.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 +38 -1
- package/README.md +87 -46
- package/dist/decompiler/vineflower.js +2 -2
- package/dist/index.js +150 -175
- package/dist/mapping-pipeline-service.d.ts +1 -1
- package/dist/mapping-pipeline-service.js +5 -5
- package/dist/mapping-service.d.ts +3 -4
- package/dist/mapping-service.js +40 -46
- package/dist/mcp-helpers.d.ts +10 -2
- package/dist/mcp-helpers.js +59 -5
- package/dist/minecraft-explorer-service.d.ts +1 -1
- package/dist/minecraft-explorer-service.js +1 -1
- package/dist/mixin-validator.js +5 -5
- package/dist/mojang-tiny-mapping-service.js +26 -26
- package/dist/resources.js +7 -7
- package/dist/search-hit-accumulator.d.ts +0 -3
- package/dist/search-hit-accumulator.js +4 -4
- package/dist/source-resolver.d.ts +1 -0
- package/dist/source-resolver.js +94 -2
- package/dist/source-service.d.ts +34 -43
- package/dist/source-service.js +597 -670
- package/dist/storage/files-repo.d.ts +9 -0
- package/dist/storage/files-repo.js +42 -0
- package/dist/storage/migrations.d.ts +1 -1
- package/dist/storage/migrations.js +6 -2
- package/dist/storage/schema.d.ts +1 -0
- package/dist/storage/schema.js +7 -0
- package/dist/tool-input.d.ts +6 -0
- package/dist/tool-input.js +64 -0
- package/dist/types.d.ts +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -3,8 +3,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { ZodError, z } from "zod";
|
|
4
4
|
import { CompatStdioServerTransport } from "./compat-stdio-transport.js";
|
|
5
5
|
import { objectResult } from "./mcp-helpers.js";
|
|
6
|
+
import { prepareToolInput } from "./tool-input.js";
|
|
6
7
|
import { loadConfig } from "./config.js";
|
|
7
|
-
import { ERROR_CODES, isAppError } from "./errors.js";
|
|
8
|
+
import { createError, ERROR_CODES, isAppError } from "./errors.js";
|
|
8
9
|
import { log } from "./logger.js";
|
|
9
10
|
import { applyNbtJsonPatch, nbtBase64ToTypedJson, typedJsonToNbtBase64 } from "./nbt/pipeline.js";
|
|
10
11
|
import { analyzeModJar } from "./mod-analyzer.js";
|
|
@@ -14,7 +15,7 @@ import { SourceService } from "./source-service.js";
|
|
|
14
15
|
if (!process.env.NODE_ENV) {
|
|
15
16
|
process.env.NODE_ENV = "production";
|
|
16
17
|
}
|
|
17
|
-
const SOURCE_MAPPINGS = ["
|
|
18
|
+
const SOURCE_MAPPINGS = ["obfuscated", "mojang", "intermediary", "yarn"];
|
|
18
19
|
const SOURCE_PRIORITIES = ["loom-first", "maven-first"];
|
|
19
20
|
const TARGET_KINDS = ["version", "jar", "coordinate"];
|
|
20
21
|
const SEARCH_INTENTS = ["symbol", "text", "path"];
|
|
@@ -43,63 +44,50 @@ const sourceModeSchema = z.enum(SOURCE_MODES);
|
|
|
43
44
|
const artifactScopeSchema = z.enum(ARTIFACT_SCOPES);
|
|
44
45
|
const decodeCompressionSchema = z.enum(DECODE_COMPRESSIONS);
|
|
45
46
|
const encodeCompressionSchema = z.enum(ENCODE_COMPRESSIONS);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
message: "targetKind and targetValue must be provided together.",
|
|
62
|
-
path: [hasTargetKind ? "targetValue" : "targetKind"]
|
|
63
|
-
});
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (!hasArtifactId && !hasTargetKind) {
|
|
67
|
-
ctx.addIssue({
|
|
68
|
-
code: z.ZodIssueCode.custom,
|
|
69
|
-
message: "Either artifactId or targetKind+targetValue must be provided.",
|
|
70
|
-
path: ["artifactId"]
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
47
|
+
const resolveArtifactTargetSchema = z.object({
|
|
48
|
+
kind: targetKindSchema,
|
|
49
|
+
value: nonEmptyString
|
|
50
|
+
});
|
|
51
|
+
const sourceLookupTargetSchema = z.discriminatedUnion("type", [
|
|
52
|
+
z.object({
|
|
53
|
+
type: z.literal("artifact"),
|
|
54
|
+
artifactId: nonEmptyString
|
|
55
|
+
}),
|
|
56
|
+
z.object({
|
|
57
|
+
type: z.literal("resolve"),
|
|
58
|
+
kind: targetKindSchema,
|
|
59
|
+
value: nonEmptyString
|
|
60
|
+
})
|
|
61
|
+
]);
|
|
74
62
|
const listVersionsShape = {
|
|
75
63
|
includeSnapshots: z.boolean().optional().describe("default false"),
|
|
76
64
|
limit: optionalPositiveInt.describe("default 20, max 200")
|
|
77
65
|
};
|
|
78
66
|
const listVersionsSchema = z.object(listVersionsShape);
|
|
79
67
|
const resolveArtifactShape = {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
68
|
+
target: z.object({
|
|
69
|
+
kind: targetKindSchema,
|
|
70
|
+
value: nonEmptyString
|
|
71
|
+
}).describe("Resolve target: { kind: version|jar|coordinate, value }"),
|
|
72
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
83
73
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
84
74
|
allowDecompile: z.boolean().optional().describe("default true"),
|
|
85
75
|
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
86
76
|
scope: artifactScopeSchema.optional().describe("vanilla = Mojang client jar only; merged = Loom cache discovery (default); loader = loader-specific"),
|
|
87
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override
|
|
77
|
+
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
88
78
|
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false.")
|
|
89
79
|
};
|
|
90
80
|
const resolveArtifactSchema = z.object(resolveArtifactShape);
|
|
91
81
|
const getClassSourceShape = {
|
|
92
82
|
className: nonEmptyString,
|
|
93
83
|
mode: sourceModeSchema.optional().describe("metadata (default) = symbol outline only; snippet = source with default maxLines=200; full = entire source"),
|
|
94
|
-
artifactId:
|
|
95
|
-
|
|
96
|
-
targetValue: optionalNonEmptyString,
|
|
97
|
-
mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn"),
|
|
84
|
+
target: sourceLookupTargetSchema.describe("Either { type: 'artifact', artifactId } or { type: 'resolve', kind, value }"),
|
|
85
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
98
86
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
99
87
|
allowDecompile: z.boolean().optional().describe("default true"),
|
|
100
88
|
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
101
89
|
scope: artifactScopeSchema.optional().describe("vanilla = Mojang client jar only; merged = Loom cache discovery (default); loader = loader-specific"),
|
|
102
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override
|
|
90
|
+
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
103
91
|
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
104
92
|
startLine: optionalPositiveInt,
|
|
105
93
|
endLine: optionalPositiveInt,
|
|
@@ -110,11 +98,6 @@ const getClassSourceShape = {
|
|
|
110
98
|
const getClassSourceSchema = z
|
|
111
99
|
.object(getClassSourceShape)
|
|
112
100
|
.superRefine((value, ctx) => {
|
|
113
|
-
validateTargetPair({
|
|
114
|
-
artifactId: value.artifactId,
|
|
115
|
-
targetKind: value.targetKind,
|
|
116
|
-
targetValue: value.targetValue
|
|
117
|
-
}, ctx);
|
|
118
101
|
if (value.startLine !== undefined &&
|
|
119
102
|
value.endLine !== undefined &&
|
|
120
103
|
value.startLine > value.endLine) {
|
|
@@ -127,10 +110,8 @@ const getClassSourceSchema = z
|
|
|
127
110
|
});
|
|
128
111
|
const getClassMembersShape = {
|
|
129
112
|
className: nonEmptyString,
|
|
130
|
-
artifactId:
|
|
131
|
-
|
|
132
|
-
targetValue: optionalNonEmptyString,
|
|
133
|
-
mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn (default official)"),
|
|
113
|
+
target: sourceLookupTargetSchema.describe("Either { type: 'artifact', artifactId } or { type: 'resolve', kind, value }"),
|
|
114
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
134
115
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
135
116
|
allowDecompile: z.boolean().optional().describe("default true"),
|
|
136
117
|
access: memberAccessSchema.optional().describe("public | all (default public)"),
|
|
@@ -143,15 +124,7 @@ const getClassMembersShape = {
|
|
|
143
124
|
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override version"),
|
|
144
125
|
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false.")
|
|
145
126
|
};
|
|
146
|
-
const getClassMembersSchema = z
|
|
147
|
-
.object(getClassMembersShape)
|
|
148
|
-
.superRefine((value, ctx) => {
|
|
149
|
-
validateTargetPair({
|
|
150
|
-
artifactId: value.artifactId,
|
|
151
|
-
targetKind: value.targetKind,
|
|
152
|
-
targetValue: value.targetValue
|
|
153
|
-
}, ctx);
|
|
154
|
-
});
|
|
127
|
+
const getClassMembersSchema = z.object(getClassMembersShape);
|
|
155
128
|
const searchClassSourceShape = {
|
|
156
129
|
artifactId: nonEmptyString,
|
|
157
130
|
query: nonEmptyString,
|
|
@@ -160,14 +133,19 @@ const searchClassSourceShape = {
|
|
|
160
133
|
packagePrefix: optionalNonEmptyString,
|
|
161
134
|
fileGlob: optionalNonEmptyString,
|
|
162
135
|
symbolKind: searchSymbolKindSchema.optional().describe("class | interface | enum | record | method | field"),
|
|
163
|
-
snippetLines: optionalPositiveInt.describe("default 8, clamp 1..80"),
|
|
164
|
-
includeDefinition: z.boolean().optional().describe("default false"),
|
|
165
|
-
includeOneHop: z.boolean().optional().describe("default false"),
|
|
166
136
|
queryMode: z.enum(["auto", "token", "literal"]).optional().describe("auto (default): FTS5 with literal fallback for separator queries; token: FTS5 only; literal: substring scan only"),
|
|
167
137
|
limit: optionalPositiveInt.describe("default 20"),
|
|
168
138
|
cursor: optionalNonEmptyString
|
|
169
139
|
};
|
|
170
|
-
const searchClassSourceSchema = z.object(searchClassSourceShape)
|
|
140
|
+
const searchClassSourceSchema = z.object(searchClassSourceShape).superRefine((value, ctx) => {
|
|
141
|
+
if (value.symbolKind && value.intent && value.intent !== "symbol") {
|
|
142
|
+
ctx.addIssue({
|
|
143
|
+
code: z.ZodIssueCode.custom,
|
|
144
|
+
path: ["symbolKind"],
|
|
145
|
+
message: 'symbolKind filter is only supported when intent="symbol".'
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
});
|
|
171
149
|
const getArtifactFileShape = {
|
|
172
150
|
artifactId: nonEmptyString,
|
|
173
151
|
filePath: nonEmptyString,
|
|
@@ -186,7 +164,7 @@ const traceSymbolLifecycleShape = {
|
|
|
186
164
|
descriptor: optionalNonEmptyString.describe('optional JVM descriptor, e.g. "(I)V"'),
|
|
187
165
|
fromVersion: optionalNonEmptyString,
|
|
188
166
|
toVersion: optionalNonEmptyString,
|
|
189
|
-
mapping: sourceMappingSchema.optional().describe("
|
|
167
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
190
168
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
191
169
|
includeSnapshots: z.boolean().optional().describe("default false"),
|
|
192
170
|
maxVersions: optionalPositiveInt.describe("default 120, max 400"),
|
|
@@ -197,7 +175,7 @@ const diffClassSignaturesShape = {
|
|
|
197
175
|
className: nonEmptyString,
|
|
198
176
|
fromVersion: nonEmptyString,
|
|
199
177
|
toVersion: nonEmptyString,
|
|
200
|
-
mapping: sourceMappingSchema.optional().describe("
|
|
178
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
201
179
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
202
180
|
};
|
|
203
181
|
const diffClassSignaturesSchema = z.object(diffClassSignaturesShape);
|
|
@@ -207,8 +185,8 @@ const findMappingShape = {
|
|
|
207
185
|
name: nonEmptyString,
|
|
208
186
|
owner: optionalNonEmptyString,
|
|
209
187
|
descriptor: optionalNonEmptyString,
|
|
210
|
-
sourceMapping: sourceMappingSchema.describe("
|
|
211
|
-
targetMapping: sourceMappingSchema.describe("
|
|
188
|
+
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
189
|
+
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
212
190
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
213
191
|
disambiguation: z
|
|
214
192
|
.object({
|
|
@@ -277,42 +255,20 @@ const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) =>
|
|
|
277
255
|
});
|
|
278
256
|
const resolveMethodMappingExactShape = {
|
|
279
257
|
version: nonEmptyString,
|
|
280
|
-
kind: workspaceSymbolKindSchema.describe("class | field | method"),
|
|
281
258
|
name: nonEmptyString,
|
|
282
|
-
owner:
|
|
283
|
-
descriptor:
|
|
284
|
-
sourceMapping: sourceMappingSchema.describe("
|
|
285
|
-
targetMapping: sourceMappingSchema.describe("
|
|
259
|
+
owner: nonEmptyString,
|
|
260
|
+
descriptor: nonEmptyString.describe("required JVM descriptor"),
|
|
261
|
+
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
262
|
+
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
286
263
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
287
264
|
};
|
|
288
265
|
const resolveMethodMappingExactSchema = z
|
|
289
266
|
.object(resolveMethodMappingExactShape)
|
|
290
267
|
.superRefine((value, ctx) => {
|
|
291
|
-
if (value.kind !== "method") {
|
|
292
|
-
ctx.addIssue({
|
|
293
|
-
code: z.ZodIssueCode.custom,
|
|
294
|
-
message: "resolve-method-mapping-exact requires kind=method.",
|
|
295
|
-
path: ["kind"]
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
if (!value.owner) {
|
|
299
|
-
ctx.addIssue({
|
|
300
|
-
code: z.ZodIssueCode.custom,
|
|
301
|
-
message: "owner is required when kind=method.",
|
|
302
|
-
path: ["owner"]
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
if (!value.descriptor) {
|
|
306
|
-
ctx.addIssue({
|
|
307
|
-
code: z.ZodIssueCode.custom,
|
|
308
|
-
message: "descriptor is required when kind=method.",
|
|
309
|
-
path: ["descriptor"]
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
268
|
if (/[\s./()]/.test(value.name)) {
|
|
313
269
|
ctx.addIssue({
|
|
314
270
|
code: z.ZodIssueCode.custom,
|
|
315
|
-
message: "name must be a simple method name
|
|
271
|
+
message: "name must be a simple method name.",
|
|
316
272
|
path: ["name"]
|
|
317
273
|
});
|
|
318
274
|
}
|
|
@@ -340,7 +296,7 @@ const classApiKindsSchema = z.string().superRefine((value, ctx) => {
|
|
|
340
296
|
const getClassApiMatrixShape = {
|
|
341
297
|
version: nonEmptyString,
|
|
342
298
|
className: nonEmptyString,
|
|
343
|
-
classNameMapping: sourceMappingSchema.describe("
|
|
299
|
+
classNameMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
344
300
|
includeKinds: classApiKindsSchema.optional().describe("comma-separated: class,field,method"),
|
|
345
301
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
346
302
|
};
|
|
@@ -352,7 +308,7 @@ const resolveWorkspaceSymbolShape = {
|
|
|
352
308
|
name: nonEmptyString,
|
|
353
309
|
owner: optionalNonEmptyString,
|
|
354
310
|
descriptor: optionalNonEmptyString,
|
|
355
|
-
sourceMapping: sourceMappingSchema.describe("
|
|
311
|
+
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
356
312
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
357
313
|
};
|
|
358
314
|
const resolveWorkspaceSymbolSchema = z
|
|
@@ -420,7 +376,7 @@ const checkSymbolExistsShape = {
|
|
|
420
376
|
owner: optionalNonEmptyString,
|
|
421
377
|
name: nonEmptyString,
|
|
422
378
|
descriptor: optionalNonEmptyString.describe("required for kind=method unless signatureMode=name-only"),
|
|
423
|
-
sourceMapping: sourceMappingSchema.describe("
|
|
379
|
+
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
424
380
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
425
381
|
nameMode: classNameModeSchema.optional().describe("fqcn | auto (default fqcn)"),
|
|
426
382
|
signatureMode: z.enum(["exact", "name-only"]).optional()
|
|
@@ -511,15 +467,28 @@ const indexArtifactShape = {
|
|
|
511
467
|
};
|
|
512
468
|
const indexArtifactSchema = z.object(indexArtifactShape);
|
|
513
469
|
const validateMixinShape = {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
470
|
+
input: z.discriminatedUnion("mode", [
|
|
471
|
+
z.object({
|
|
472
|
+
mode: z.literal("inline"),
|
|
473
|
+
source: nonEmptyString.describe("Mixin Java source text")
|
|
474
|
+
}),
|
|
475
|
+
z.object({
|
|
476
|
+
mode: z.literal("path"),
|
|
477
|
+
path: nonEmptyString.describe("Path to a Mixin .java file")
|
|
478
|
+
}),
|
|
479
|
+
z.object({
|
|
480
|
+
mode: z.literal("paths"),
|
|
481
|
+
paths: z.array(nonEmptyString).min(1).describe("Array of Mixin .java file paths for batch validation")
|
|
482
|
+
}),
|
|
483
|
+
z.object({
|
|
484
|
+
mode: z.literal("config"),
|
|
485
|
+
configPaths: z.array(nonEmptyString).min(1).describe("Path array to mixin config JSON files (e.g. modid.mixins.json)")
|
|
486
|
+
})
|
|
487
|
+
]),
|
|
519
488
|
sourceRoots: z.array(z.string().min(1)).optional()
|
|
520
489
|
.describe("Array of source roots for multi-module projects (e.g. ['common/src/main/java', 'neoforge/src/main/java'])"),
|
|
521
490
|
version: nonEmptyString.describe("Minecraft version"),
|
|
522
|
-
mapping: sourceMappingSchema.optional().describe("
|
|
491
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
523
492
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
524
493
|
scope: artifactScopeSchema.optional().describe("vanilla | merged | loader"),
|
|
525
494
|
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
@@ -541,18 +510,11 @@ const validateMixinShape = {
|
|
|
541
510
|
treatInfoAsWarning: z.boolean().optional()
|
|
542
511
|
.describe("When false, suppress info-severity structured warnings from output (default true)")
|
|
543
512
|
};
|
|
544
|
-
const validateMixinSchema = z.object(validateMixinShape)
|
|
545
|
-
const hasSource = d.source != null;
|
|
546
|
-
const hasSourcePath = d.sourcePath != null;
|
|
547
|
-
const hasSourcePaths = d.sourcePaths != null && d.sourcePaths.length > 0;
|
|
548
|
-
const hasMixinConfig = d.mixinConfigPath != null && (typeof d.mixinConfigPath === "string" || (Array.isArray(d.mixinConfigPath) && d.mixinConfigPath.length > 0));
|
|
549
|
-
// Exactly one of the four must be provided
|
|
550
|
-
return [hasSource, hasSourcePath, hasSourcePaths, hasMixinConfig].filter(Boolean).length === 1;
|
|
551
|
-
}, { message: "Exactly one of 'source', 'sourcePath', 'sourcePaths', or 'mixinConfigPath' must be provided." });
|
|
513
|
+
const validateMixinSchema = z.object(validateMixinShape);
|
|
552
514
|
const validateAccessWidenerShape = {
|
|
553
515
|
content: nonEmptyString.describe("Access Widener file content"),
|
|
554
516
|
version: nonEmptyString.describe("Minecraft version"),
|
|
555
|
-
mapping: sourceMappingSchema.optional().describe("
|
|
517
|
+
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
556
518
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
557
519
|
};
|
|
558
520
|
const validateAccessWidenerSchema = z.object(validateAccessWidenerShape);
|
|
@@ -672,11 +634,16 @@ function attachProcessErrorHandlers() {
|
|
|
672
634
|
function buildRequestId() {
|
|
673
635
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
674
636
|
}
|
|
675
|
-
function
|
|
676
|
-
if (
|
|
677
|
-
return
|
|
637
|
+
function normalizeSourceLookupTarget(target) {
|
|
638
|
+
if (target.type === "artifact") {
|
|
639
|
+
return { artifactId: target.artifactId };
|
|
678
640
|
}
|
|
679
|
-
return {
|
|
641
|
+
return {
|
|
642
|
+
target: {
|
|
643
|
+
kind: target.kind,
|
|
644
|
+
value: target.value
|
|
645
|
+
}
|
|
646
|
+
};
|
|
680
647
|
}
|
|
681
648
|
function parseClassApiKinds(value) {
|
|
682
649
|
if (value == null) {
|
|
@@ -857,7 +824,28 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
857
824
|
const requestId = buildRequestId();
|
|
858
825
|
const startedAt = Date.now();
|
|
859
826
|
try {
|
|
860
|
-
const
|
|
827
|
+
const { normalizedInput, removedOfficialPaths, suggestedReplacementInput } = prepareToolInput(rawInput);
|
|
828
|
+
if (removedOfficialPaths.length > 0) {
|
|
829
|
+
throw createError({
|
|
830
|
+
code: ERROR_CODES.INVALID_INPUT,
|
|
831
|
+
message: `The "official" mapping namespace was removed. Use "obfuscated" instead.`,
|
|
832
|
+
details: {
|
|
833
|
+
fieldErrors: removedOfficialPaths.map((path) => ({
|
|
834
|
+
path,
|
|
835
|
+
message: `"official" is no longer supported for this field. Use "obfuscated".`,
|
|
836
|
+
code: "invalid_enum_value"
|
|
837
|
+
})),
|
|
838
|
+
nextAction: `Replace "official" with "obfuscated" in mapping-related fields and retry.`,
|
|
839
|
+
suggestedCall: suggestedReplacementInput
|
|
840
|
+
? {
|
|
841
|
+
tool,
|
|
842
|
+
params: suggestedReplacementInput
|
|
843
|
+
}
|
|
844
|
+
: undefined
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
const parsedInput = schema.parse(normalizedInput);
|
|
861
849
|
const payload = await action(parsedInput);
|
|
862
850
|
const { result, warnings } = splitWarnings(payload);
|
|
863
851
|
return objectResult({
|
|
@@ -910,18 +898,15 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
910
898
|
durationMs: Date.now() - startedAt,
|
|
911
899
|
warnings: []
|
|
912
900
|
}
|
|
913
|
-
});
|
|
901
|
+
}, { isError: true });
|
|
914
902
|
}
|
|
915
903
|
}
|
|
916
904
|
server.tool("list-versions", "List available Minecraft versions from Mojang manifest and locally cached version jars.", listVersionsShape, { readOnlyHint: true }, async (args) => runTool("list-versions", args, listVersionsSchema, async (input) => sourceService.listVersions({
|
|
917
905
|
includeSnapshots: input.includeSnapshots,
|
|
918
906
|
limit: input.limit
|
|
919
907
|
})));
|
|
920
|
-
server.tool("resolve-artifact", "Resolve source artifact from
|
|
921
|
-
target:
|
|
922
|
-
kind: input.targetKind,
|
|
923
|
-
value: input.targetValue
|
|
924
|
-
},
|
|
908
|
+
server.tool("resolve-artifact", "Resolve source artifact from a target object ({ kind, value }) and return artifact metadata. For target.kind=jar, only <basename>-sources.jar is auto-adopted; other adjacent *-sources.jar files are informational.", resolveArtifactShape, { readOnlyHint: true }, async (args) => runTool("resolve-artifact", args, resolveArtifactSchema, async (input) => sourceService.resolveArtifact({
|
|
909
|
+
target: input.target,
|
|
925
910
|
mapping: input.mapping,
|
|
926
911
|
sourcePriority: input.sourcePriority,
|
|
927
912
|
allowDecompile: input.allowDecompile,
|
|
@@ -941,42 +926,48 @@ server.tool("find-class", "Resolve a simple or qualified class name to fully-qua
|
|
|
941
926
|
artifactId: input.artifactId,
|
|
942
927
|
limit: input.limit
|
|
943
928
|
})));
|
|
944
|
-
server.tool("get-class-source", "Get Java source for a class by artifactId or
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
929
|
+
server.tool("get-class-source", "Get Java source for a class by target ({ type: 'artifact', artifactId } or { type: 'resolve', kind, value }). Default mode=metadata returns symbol outline only; use mode=snippet for bounded excerpts or mode=full for entire source.", getClassSourceShape, { readOnlyHint: true }, async (args) => runTool("get-class-source", args, getClassSourceSchema, async (input) => {
|
|
930
|
+
const normalizedTarget = normalizeSourceLookupTarget(input.target);
|
|
931
|
+
return sourceService.getClassSource({
|
|
932
|
+
className: input.className,
|
|
933
|
+
mode: input.mode,
|
|
934
|
+
artifactId: normalizedTarget.artifactId,
|
|
935
|
+
target: normalizedTarget.target,
|
|
936
|
+
mapping: input.mapping,
|
|
937
|
+
sourcePriority: input.sourcePriority,
|
|
938
|
+
allowDecompile: input.allowDecompile,
|
|
939
|
+
projectPath: input.projectPath,
|
|
940
|
+
scope: input.scope,
|
|
941
|
+
preferProjectVersion: input.preferProjectVersion,
|
|
942
|
+
strictVersion: input.strictVersion,
|
|
943
|
+
startLine: input.startLine,
|
|
944
|
+
endLine: input.endLine,
|
|
945
|
+
maxLines: input.maxLines,
|
|
946
|
+
maxChars: input.maxChars,
|
|
947
|
+
outputFile: input.outputFile
|
|
948
|
+
});
|
|
949
|
+
}));
|
|
950
|
+
server.tool("get-class-members", "Get fields/methods/constructors for one class from binary bytecode by target ({ type: 'artifact', artifactId } or { type: 'resolve', kind, value }).", getClassMembersShape, { readOnlyHint: true }, async (args) => runTool("get-class-members", args, getClassMembersSchema, async (input) => {
|
|
951
|
+
const normalizedTarget = normalizeSourceLookupTarget(input.target);
|
|
952
|
+
return sourceService.getClassMembers({
|
|
953
|
+
className: input.className,
|
|
954
|
+
artifactId: normalizedTarget.artifactId,
|
|
955
|
+
target: normalizedTarget.target,
|
|
956
|
+
mapping: input.mapping,
|
|
957
|
+
sourcePriority: input.sourcePriority,
|
|
958
|
+
allowDecompile: input.allowDecompile,
|
|
959
|
+
access: input.access,
|
|
960
|
+
includeSynthetic: input.includeSynthetic,
|
|
961
|
+
includeInherited: input.includeInherited,
|
|
962
|
+
memberPattern: input.memberPattern,
|
|
963
|
+
maxMembers: input.maxMembers,
|
|
964
|
+
projectPath: input.projectPath,
|
|
965
|
+
scope: input.scope,
|
|
966
|
+
preferProjectVersion: input.preferProjectVersion,
|
|
967
|
+
strictVersion: input.strictVersion
|
|
968
|
+
});
|
|
969
|
+
}));
|
|
970
|
+
server.tool("search-class-source", "Search indexed class source files for one artifact with symbol/text/path intent and compact hit output.", searchClassSourceShape, { readOnlyHint: true }, async (args) => runTool("search-class-source", args, searchClassSourceSchema, async (input) => {
|
|
980
971
|
const scope = input.packagePrefix || input.fileGlob || input.symbolKind
|
|
981
972
|
? {
|
|
982
973
|
packagePrefix: input.packagePrefix,
|
|
@@ -984,22 +975,12 @@ server.tool("search-class-source", "Search indexed class source files for one ar
|
|
|
984
975
|
symbolKind: input.symbolKind
|
|
985
976
|
}
|
|
986
977
|
: undefined;
|
|
987
|
-
const include = input.snippetLines !== undefined ||
|
|
988
|
-
input.includeDefinition !== undefined ||
|
|
989
|
-
input.includeOneHop !== undefined
|
|
990
|
-
? {
|
|
991
|
-
snippetLines: input.snippetLines,
|
|
992
|
-
includeDefinition: input.includeDefinition,
|
|
993
|
-
includeOneHop: input.includeOneHop
|
|
994
|
-
}
|
|
995
|
-
: undefined;
|
|
996
978
|
return sourceService.searchClassSource({
|
|
997
979
|
artifactId: input.artifactId,
|
|
998
980
|
query: input.query,
|
|
999
981
|
intent: input.intent,
|
|
1000
982
|
match: input.match,
|
|
1001
983
|
scope: scope,
|
|
1002
|
-
include,
|
|
1003
984
|
queryMode: input.queryMode,
|
|
1004
985
|
limit: input.limit,
|
|
1005
986
|
cursor: input.cursor
|
|
@@ -1042,7 +1023,6 @@ server.tool("find-mapping", "Find symbol mapping candidates between namespaces u
|
|
|
1042
1023
|
})));
|
|
1043
1024
|
server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly by owner+name+descriptor between namespaces and report resolved/not_found/ambiguous.", resolveMethodMappingExactShape, { readOnlyHint: true }, async (args) => runTool("resolve-method-mapping-exact", args, resolveMethodMappingExactSchema, async (input) => sourceService.resolveMethodMappingExact({
|
|
1044
1025
|
version: input.version,
|
|
1045
|
-
kind: input.kind,
|
|
1046
1026
|
name: input.name,
|
|
1047
1027
|
owner: input.owner,
|
|
1048
1028
|
descriptor: input.descriptor,
|
|
@@ -1050,7 +1030,7 @@ server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly
|
|
|
1050
1030
|
targetMapping: input.targetMapping,
|
|
1051
1031
|
sourcePriority: input.sourcePriority
|
|
1052
1032
|
})));
|
|
1053
|
-
server.tool("get-class-api-matrix", "List class/member API rows across
|
|
1033
|
+
server.tool("get-class-api-matrix", "List class/member API rows across obfuscated/mojang/intermediary/yarn mappings for one class and Minecraft version.", getClassApiMatrixShape, { readOnlyHint: true }, async (args) => runTool("get-class-api-matrix", args, getClassApiMatrixSchema, async (input) => sourceService.getClassApiMatrix({
|
|
1054
1034
|
version: input.version,
|
|
1055
1035
|
className: input.className,
|
|
1056
1036
|
classNameMapping: input.classNameMapping,
|
|
@@ -1096,11 +1076,7 @@ server.tool("index-artifact", "Rebuild indexed files/symbols metadata for an exi
|
|
|
1096
1076
|
})));
|
|
1097
1077
|
server.tool("get-runtime-metrics", "Get runtime service counters and latency snapshots for cache/search/index diagnostics.", { readOnlyHint: true }, async (args) => runTool("get-runtime-metrics", args, emptySchema, async () => Promise.resolve(sourceService.getRuntimeMetrics())));
|
|
1098
1078
|
server.tool("validate-mixin", "Validate Mixin source against Minecraft bytecode signatures for a given version.", validateMixinShape, { readOnlyHint: true }, async (args) => runTool("validate-mixin", args, validateMixinSchema, async (input) => sourceService.validateMixin({
|
|
1099
|
-
|
|
1100
|
-
sourcePath: input.sourcePath,
|
|
1101
|
-
sourcePaths: input.sourcePaths,
|
|
1102
|
-
mixinConfigPath: input.mixinConfigPath,
|
|
1103
|
-
sourceRoot: input.sourceRoot,
|
|
1079
|
+
input: input.input,
|
|
1104
1080
|
sourceRoots: input.sourceRoots,
|
|
1105
1081
|
version: input.version,
|
|
1106
1082
|
mapping: input.mapping,
|
|
@@ -1182,7 +1158,6 @@ export async function startServer() {
|
|
|
1182
1158
|
// In stdio mode, explicitly resume stdin so JSON-RPC lines are consumed.
|
|
1183
1159
|
process.stdin.resume();
|
|
1184
1160
|
serverStarted = true;
|
|
1185
|
-
setImmediate(getSourceService); // Eagerly init SourceService during MCP handshake
|
|
1186
1161
|
}
|
|
1187
1162
|
export { server, sourceService, config, SERVER_VERSION };
|
|
1188
1163
|
//# sourceMappingURL=index.js.map
|
|
@@ -12,7 +12,7 @@ export interface MappingPipelineResult {
|
|
|
12
12
|
/**
|
|
13
13
|
* Mapping pipeline for v0.3.
|
|
14
14
|
* Current implementation enforces explicit guarantees:
|
|
15
|
-
* -
|
|
15
|
+
* - obfuscated: always pass-through
|
|
16
16
|
* - mojang: requires source-backed artifact; decompile-only artifacts are rejected
|
|
17
17
|
*/
|
|
18
18
|
export declare function applyMappingPipeline(input: MappingPipelineInput): MappingPipelineResult;
|
|
@@ -2,14 +2,14 @@ import { createError, ERROR_CODES } from "./errors.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Mapping pipeline for v0.3.
|
|
4
4
|
* Current implementation enforces explicit guarantees:
|
|
5
|
-
* -
|
|
5
|
+
* - obfuscated: always pass-through
|
|
6
6
|
* - mojang: requires source-backed artifact; decompile-only artifacts are rejected
|
|
7
7
|
*/
|
|
8
8
|
export function applyMappingPipeline(input) {
|
|
9
9
|
const transformChain = [];
|
|
10
10
|
const qualityFlags = [];
|
|
11
|
-
if (input.requestedMapping === "
|
|
12
|
-
transformChain.push("mapping:
|
|
11
|
+
if (input.requestedMapping === "obfuscated") {
|
|
12
|
+
transformChain.push("mapping:obfuscated-pass-through");
|
|
13
13
|
if (input.resolved.isDecompiled) {
|
|
14
14
|
qualityFlags.push("decompiled");
|
|
15
15
|
}
|
|
@@ -17,7 +17,7 @@ export function applyMappingPipeline(input) {
|
|
|
17
17
|
qualityFlags.push("source-backed");
|
|
18
18
|
}
|
|
19
19
|
return {
|
|
20
|
-
mappingApplied: "
|
|
20
|
+
mappingApplied: "obfuscated",
|
|
21
21
|
qualityFlags,
|
|
22
22
|
transformChain
|
|
23
23
|
};
|
|
@@ -45,7 +45,7 @@ export function applyMappingPipeline(input) {
|
|
|
45
45
|
origin: input.resolved.origin,
|
|
46
46
|
binaryJarPath: input.resolved.binaryJarPath,
|
|
47
47
|
sourceJarPath: input.resolved.sourceJarPath,
|
|
48
|
-
nextAction: "Provide a source-backed artifact (source jar) or use mapping=
|
|
48
|
+
nextAction: "Provide a source-backed artifact (source jar) or use mapping=obfuscated."
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
}
|
|
@@ -78,10 +78,9 @@ export type EnsureMappingAvailableOutput = {
|
|
|
78
78
|
};
|
|
79
79
|
export type ResolveMethodMappingExactInput = {
|
|
80
80
|
version: string;
|
|
81
|
-
kind: SymbolQueryKind;
|
|
82
81
|
name: string;
|
|
83
|
-
owner
|
|
84
|
-
descriptor
|
|
82
|
+
owner: string;
|
|
83
|
+
descriptor: string;
|
|
85
84
|
sourceMapping: SourceMapping;
|
|
86
85
|
targetMapping: SourceMapping;
|
|
87
86
|
sourcePriority?: MappingSourcePriority;
|
|
@@ -104,7 +103,7 @@ export type ClassApiMatrixEntry = {
|
|
|
104
103
|
export type ClassApiMatrixRow = {
|
|
105
104
|
kind: ClassApiMatrixKind;
|
|
106
105
|
descriptor?: string;
|
|
107
|
-
|
|
106
|
+
obfuscated?: ClassApiMatrixEntry;
|
|
108
107
|
mojang?: ClassApiMatrixEntry;
|
|
109
108
|
intermediary?: ClassApiMatrixEntry;
|
|
110
109
|
yarn?: ClassApiMatrixEntry;
|