@adhisang/minecraft-modding-mcp 1.0.0 → 1.1.1

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/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { MCPServer, object } from "mcp-use/server";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { ZodError, z } from "zod";
4
+ import { CompatStdioServerTransport } from "./compat-stdio-transport.js";
5
+ import { objectResult } from "./mcp-helpers.js";
4
6
  import { loadConfig } from "./config.js";
5
7
  import { ERROR_CODES, isAppError } from "./errors.js";
6
8
  import { log } from "./logger.js";
@@ -63,30 +65,33 @@ function validateTargetPair(value, ctx) {
63
65
  });
64
66
  }
65
67
  }
66
- const listVersionsSchema = z.object({
67
- includeSnapshots: z.boolean().optional(),
68
- limit: optionalPositiveInt
69
- });
70
- const resolveArtifactSchema = z.object({
71
- targetKind: targetKindSchema,
68
+ const listVersionsShape = {
69
+ includeSnapshots: z.boolean().optional().describe("default false"),
70
+ limit: optionalPositiveInt.describe("default 20, max 200")
71
+ };
72
+ const listVersionsSchema = z.object(listVersionsShape);
73
+ const resolveArtifactShape = {
74
+ targetKind: targetKindSchema.describe("version | jar | coordinate"),
72
75
  targetValue: nonEmptyString,
73
- mapping: sourceMappingSchema.optional(),
74
- sourcePriority: mappingSourcePrioritySchema.optional(),
75
- allowDecompile: z.boolean().optional()
76
- });
77
- const getClassSourceSchema = z
78
- .object({
76
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn"),
77
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
78
+ allowDecompile: z.boolean().optional().describe("default true")
79
+ };
80
+ const resolveArtifactSchema = z.object(resolveArtifactShape);
81
+ const getClassSourceShape = {
79
82
  className: nonEmptyString,
80
83
  artifactId: optionalNonEmptyString,
81
- targetKind: targetKindSchema.optional(),
84
+ targetKind: targetKindSchema.optional().describe("version | jar | coordinate"),
82
85
  targetValue: optionalNonEmptyString,
83
- mapping: sourceMappingSchema.optional(),
84
- sourcePriority: mappingSourcePrioritySchema.optional(),
85
- allowDecompile: z.boolean().optional(),
86
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn"),
87
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
88
+ allowDecompile: z.boolean().optional().describe("default true"),
86
89
  startLine: optionalPositiveInt,
87
90
  endLine: optionalPositiveInt,
88
91
  maxLines: optionalPositiveInt
89
- })
92
+ };
93
+ const getClassSourceSchema = z
94
+ .object(getClassSourceShape)
90
95
  .superRefine((value, ctx) => {
91
96
  validateTargetPair({
92
97
  artifactId: value.artifactId,
@@ -103,21 +108,22 @@ const getClassSourceSchema = z
103
108
  });
104
109
  }
105
110
  });
106
- const getClassMembersSchema = z
107
- .object({
111
+ const getClassMembersShape = {
108
112
  className: nonEmptyString,
109
113
  artifactId: optionalNonEmptyString,
110
- targetKind: targetKindSchema.optional(),
114
+ targetKind: targetKindSchema.optional().describe("version | jar | coordinate"),
111
115
  targetValue: optionalNonEmptyString,
112
- mapping: sourceMappingSchema.optional(),
113
- sourcePriority: mappingSourcePrioritySchema.optional(),
114
- allowDecompile: z.boolean().optional(),
115
- access: memberAccessSchema.optional(),
116
- includeSynthetic: z.boolean().optional(),
117
- includeInherited: z.boolean().optional(),
116
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn (default official)"),
117
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
118
+ allowDecompile: z.boolean().optional().describe("default true"),
119
+ access: memberAccessSchema.optional().describe("public | all (default public)"),
120
+ includeSynthetic: z.boolean().optional().describe("default false"),
121
+ includeInherited: z.boolean().optional().describe("default false"),
118
122
  memberPattern: optionalNonEmptyString,
119
- maxMembers: optionalPositiveInt
120
- })
123
+ maxMembers: optionalPositiveInt.describe("default 500, max 5000")
124
+ };
125
+ const getClassMembersSchema = z
126
+ .object(getClassMembersShape)
121
127
  .superRefine((value, ctx) => {
122
128
  validateTargetPair({
123
129
  artifactId: value.artifactId,
@@ -125,59 +131,65 @@ const getClassMembersSchema = z
125
131
  targetValue: value.targetValue
126
132
  }, ctx);
127
133
  });
128
- const searchClassSourceSchema = z.object({
134
+ const searchClassSourceShape = {
129
135
  artifactId: nonEmptyString,
130
136
  query: nonEmptyString,
131
- intent: searchIntentSchema.optional(),
132
- match: searchMatchSchema.optional(),
137
+ intent: searchIntentSchema.optional().describe("symbol | text | path"),
138
+ match: searchMatchSchema.optional().describe("exact | prefix | contains | regex"),
133
139
  packagePrefix: optionalNonEmptyString,
134
140
  fileGlob: optionalNonEmptyString,
135
- symbolKind: searchSymbolKindSchema.optional(),
136
- snippetLines: optionalPositiveInt,
137
- includeDefinition: z.boolean().optional(),
138
- includeOneHop: z.boolean().optional(),
139
- limit: optionalPositiveInt,
141
+ symbolKind: searchSymbolKindSchema.optional().describe("class | interface | enum | record | method | field"),
142
+ snippetLines: optionalPositiveInt.describe("default 8, clamp 1..80"),
143
+ includeDefinition: z.boolean().optional().describe("default false"),
144
+ includeOneHop: z.boolean().optional().describe("default false"),
145
+ limit: optionalPositiveInt.describe("default 20"),
140
146
  cursor: optionalNonEmptyString
141
- });
142
- const getArtifactFileSchema = z.object({
147
+ };
148
+ const searchClassSourceSchema = z.object(searchClassSourceShape);
149
+ const getArtifactFileShape = {
143
150
  artifactId: nonEmptyString,
144
151
  filePath: nonEmptyString,
145
152
  maxBytes: optionalPositiveInt
146
- });
147
- const listArtifactFilesSchema = z.object({
153
+ };
154
+ const getArtifactFileSchema = z.object(getArtifactFileShape);
155
+ const listArtifactFilesShape = {
148
156
  artifactId: nonEmptyString,
149
157
  prefix: optionalNonEmptyString,
150
158
  limit: optionalPositiveInt,
151
159
  cursor: optionalNonEmptyString
152
- });
153
- const traceSymbolLifecycleSchema = z.object({
154
- symbol: nonEmptyString,
155
- descriptor: optionalNonEmptyString,
160
+ };
161
+ const listArtifactFilesSchema = z.object(listArtifactFilesShape);
162
+ const traceSymbolLifecycleShape = {
163
+ symbol: nonEmptyString.describe("fully.qualified.Class.method"),
164
+ descriptor: optionalNonEmptyString.describe('optional JVM descriptor, e.g. "(I)V"'),
156
165
  fromVersion: optionalNonEmptyString,
157
166
  toVersion: optionalNonEmptyString,
158
- mapping: sourceMappingSchema.optional(),
159
- sourcePriority: mappingSourcePrioritySchema.optional(),
160
- includeSnapshots: z.boolean().optional(),
161
- maxVersions: optionalPositiveInt,
162
- includeTimeline: z.boolean().optional()
163
- });
164
- const diffClassSignaturesSchema = z.object({
167
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn (default official)"),
168
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
169
+ includeSnapshots: z.boolean().optional().describe("default false"),
170
+ maxVersions: optionalPositiveInt.describe("default 120, max 400"),
171
+ includeTimeline: z.boolean().optional().describe("default false")
172
+ };
173
+ const traceSymbolLifecycleSchema = z.object(traceSymbolLifecycleShape);
174
+ const diffClassSignaturesShape = {
165
175
  className: nonEmptyString,
166
176
  fromVersion: nonEmptyString,
167
177
  toVersion: nonEmptyString,
168
- mapping: sourceMappingSchema.optional(),
169
- sourcePriority: mappingSourcePrioritySchema.optional()
170
- });
171
- const findMappingSchema = z.object({
178
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn (default official)"),
179
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
180
+ };
181
+ const diffClassSignaturesSchema = z.object(diffClassSignaturesShape);
182
+ const findMappingShape = {
172
183
  version: nonEmptyString,
173
- kind: workspaceSymbolKindSchema,
184
+ kind: workspaceSymbolKindSchema.describe("class | field | method"),
174
185
  name: nonEmptyString,
175
186
  owner: optionalNonEmptyString,
176
187
  descriptor: optionalNonEmptyString,
177
- sourceMapping: sourceMappingSchema,
178
- targetMapping: sourceMappingSchema,
179
- sourcePriority: mappingSourcePrioritySchema.optional()
180
- }).superRefine((value, ctx) => {
188
+ sourceMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
189
+ targetMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
190
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
191
+ };
192
+ const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) => {
181
193
  if (value.kind === "class") {
182
194
  if (value.owner) {
183
195
  ctx.addIssue({
@@ -234,17 +246,18 @@ const findMappingSchema = z.object({
234
246
  });
235
247
  }
236
248
  });
237
- const resolveMethodMappingExactSchema = z
238
- .object({
249
+ const resolveMethodMappingExactShape = {
239
250
  version: nonEmptyString,
240
- kind: workspaceSymbolKindSchema,
251
+ kind: workspaceSymbolKindSchema.describe("class | field | method"),
241
252
  name: nonEmptyString,
242
253
  owner: optionalNonEmptyString,
243
- descriptor: optionalNonEmptyString,
244
- sourceMapping: sourceMappingSchema,
245
- targetMapping: sourceMappingSchema,
246
- sourcePriority: mappingSourcePrioritySchema.optional()
247
- })
254
+ descriptor: optionalNonEmptyString.describe("required for kind=method"),
255
+ sourceMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
256
+ targetMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
257
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
258
+ };
259
+ const resolveMethodMappingExactSchema = z
260
+ .object(resolveMethodMappingExactShape)
248
261
  .superRefine((value, ctx) => {
249
262
  if (value.kind !== "method") {
250
263
  ctx.addIssue({
@@ -295,24 +308,26 @@ const classApiKindsSchema = z.string().superRefine((value, ctx) => {
295
308
  });
296
309
  }
297
310
  });
298
- const getClassApiMatrixSchema = z.object({
311
+ const getClassApiMatrixShape = {
299
312
  version: nonEmptyString,
300
313
  className: nonEmptyString,
301
- classNameMapping: sourceMappingSchema,
302
- includeKinds: classApiKindsSchema.optional(),
303
- sourcePriority: mappingSourcePrioritySchema.optional()
304
- });
305
- const resolveWorkspaceSymbolSchema = z
306
- .object({
314
+ classNameMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
315
+ includeKinds: classApiKindsSchema.optional().describe("comma-separated: class,field,method"),
316
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
317
+ };
318
+ const getClassApiMatrixSchema = z.object(getClassApiMatrixShape);
319
+ const resolveWorkspaceSymbolShape = {
307
320
  projectPath: nonEmptyString,
308
321
  version: nonEmptyString,
309
- kind: workspaceSymbolKindSchema,
322
+ kind: workspaceSymbolKindSchema.describe("class | field | method"),
310
323
  name: nonEmptyString,
311
324
  owner: optionalNonEmptyString,
312
325
  descriptor: optionalNonEmptyString,
313
- sourceMapping: sourceMappingSchema,
314
- sourcePriority: mappingSourcePrioritySchema.optional()
315
- })
326
+ sourceMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
327
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
328
+ };
329
+ const resolveWorkspaceSymbolSchema = z
330
+ .object(resolveWorkspaceSymbolShape)
316
331
  .superRefine((value, ctx) => {
317
332
  if (value.kind === "class") {
318
333
  if (value.owner) {
@@ -370,15 +385,16 @@ const resolveWorkspaceSymbolSchema = z
370
385
  });
371
386
  }
372
387
  });
373
- const checkSymbolExistsSchema = z.object({
388
+ const checkSymbolExistsShape = {
374
389
  version: nonEmptyString,
375
- kind: workspaceSymbolKindSchema,
390
+ kind: workspaceSymbolKindSchema.describe("class | field | method"),
376
391
  owner: optionalNonEmptyString,
377
392
  name: nonEmptyString,
378
- descriptor: optionalNonEmptyString,
379
- sourceMapping: sourceMappingSchema,
380
- sourcePriority: mappingSourcePrioritySchema.optional()
381
- }).superRefine((value, ctx) => {
393
+ descriptor: optionalNonEmptyString.describe("required for kind=method"),
394
+ sourceMapping: sourceMappingSchema.describe("official | mojang | intermediary | yarn"),
395
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
396
+ };
397
+ const checkSymbolExistsSchema = z.object(checkSymbolExistsShape).superRefine((value, ctx) => {
382
398
  if (value.kind === "class") {
383
399
  if (value.owner) {
384
400
  ctx.addIssue({
@@ -435,10 +451,11 @@ const checkSymbolExistsSchema = z.object({
435
451
  });
436
452
  }
437
453
  });
438
- const nbtToJsonSchema = z.object({
454
+ const nbtToJsonShape = {
439
455
  nbtBase64: nonEmptyString,
440
- compression: decodeCompressionSchema.optional()
441
- });
456
+ compression: decodeCompressionSchema.optional().describe("none | gzip | auto (default auto)")
457
+ };
458
+ const nbtToJsonSchema = z.object(nbtToJsonShape);
442
459
  const nbtPatchOperationSchema = z
443
460
  .object({
444
461
  op: z.enum(["add", "remove", "replace", "test"]),
@@ -446,71 +463,83 @@ const nbtPatchOperationSchema = z
446
463
  value: z.unknown().optional()
447
464
  })
448
465
  .passthrough();
449
- const nbtApplyJsonPatchSchema = z.object({
466
+ const nbtApplyJsonPatchShape = {
450
467
  typedJson: z.unknown(),
451
- patch: z.array(nbtPatchOperationSchema)
452
- });
453
- const jsonToNbtSchema = z.object({
468
+ patch: z.array(nbtPatchOperationSchema).describe("RFC6902 operation array (add/remove/replace/test)")
469
+ };
470
+ const nbtApplyJsonPatchSchema = z.object(nbtApplyJsonPatchShape);
471
+ const jsonToNbtShape = {
454
472
  typedJson: z.unknown(),
455
- compression: encodeCompressionSchema.optional()
456
- });
457
- const indexArtifactSchema = z.object({
473
+ compression: encodeCompressionSchema.optional().describe("none | gzip (default none)")
474
+ };
475
+ const jsonToNbtSchema = z.object(jsonToNbtShape);
476
+ const indexArtifactShape = {
458
477
  artifactId: nonEmptyString,
459
- force: z.boolean().optional()
460
- });
461
- const validateMixinSchema = z.object({
462
- source: nonEmptyString,
463
- version: nonEmptyString,
464
- mapping: sourceMappingSchema.optional(),
465
- sourcePriority: mappingSourcePrioritySchema.optional()
466
- });
467
- const validateAccessWidenerSchema = z.object({
468
- content: nonEmptyString,
469
- version: nonEmptyString,
470
- mapping: sourceMappingSchema.optional(),
471
- sourcePriority: mappingSourcePrioritySchema.optional()
472
- });
473
- const analyzeModJarSchema = z.object({
474
- jarPath: nonEmptyString,
475
- includeClasses: z.boolean().optional()
476
- });
477
- const getRegistryDataSchema = z.object({
478
- version: nonEmptyString,
479
- registry: optionalNonEmptyString
480
- });
478
+ force: z.boolean().optional().describe("default false")
479
+ };
480
+ const indexArtifactSchema = z.object(indexArtifactShape);
481
+ const validateMixinShape = {
482
+ source: nonEmptyString.describe("Mixin Java source text"),
483
+ version: nonEmptyString.describe("Minecraft version"),
484
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn"),
485
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
486
+ };
487
+ const validateMixinSchema = z.object(validateMixinShape);
488
+ const validateAccessWidenerShape = {
489
+ content: nonEmptyString.describe("Access Widener file content"),
490
+ version: nonEmptyString.describe("Minecraft version"),
491
+ mapping: sourceMappingSchema.optional().describe("official | mojang | intermediary | yarn"),
492
+ sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
493
+ };
494
+ const validateAccessWidenerSchema = z.object(validateAccessWidenerShape);
495
+ const analyzeModJarShape = {
496
+ jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
497
+ includeClasses: z.boolean().optional().describe("Include full class listing (default false)")
498
+ };
499
+ const analyzeModJarSchema = z.object(analyzeModJarShape);
500
+ const getRegistryDataShape = {
501
+ version: nonEmptyString.describe("Minecraft version (e.g. 1.21)"),
502
+ registry: optionalNonEmptyString.describe('Optional registry name (e.g. "block", "item", "minecraft:biome"). Omit to list all registries.')
503
+ };
504
+ const getRegistryDataSchema = z.object(getRegistryDataShape);
481
505
  const COMPARE_VERSIONS_CATEGORIES = ["classes", "registry", "all"];
482
506
  const compareVersionsCategorySchema = z.enum(COMPARE_VERSIONS_CATEGORIES);
483
- const compareVersionsSchema = z.object({
484
- fromVersion: nonEmptyString,
485
- toVersion: nonEmptyString,
486
- category: compareVersionsCategorySchema.optional(),
487
- packageFilter: optionalNonEmptyString,
488
- maxClassResults: optionalPositiveInt
489
- });
490
- const decompileModJarSchema = z.object({
491
- jarPath: nonEmptyString,
492
- className: optionalNonEmptyString
493
- });
494
- const getModClassSourceSchema = z.object({
495
- jarPath: nonEmptyString,
496
- className: nonEmptyString
497
- });
507
+ const compareVersionsShape = {
508
+ fromVersion: nonEmptyString.describe("Older Minecraft version (e.g. 1.20.4)"),
509
+ toVersion: nonEmptyString.describe("Newer Minecraft version (e.g. 1.21)"),
510
+ category: compareVersionsCategorySchema.optional().describe("classes | registry | all (default all)"),
511
+ packageFilter: optionalNonEmptyString.describe("Filter classes to a package prefix (e.g. net.minecraft.world.item)"),
512
+ maxClassResults: optionalPositiveInt.describe("Max class results per direction (default 500, max 5000)")
513
+ };
514
+ const compareVersionsSchema = z.object(compareVersionsShape);
515
+ const decompileModJarShape = {
516
+ jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
517
+ className: optionalNonEmptyString.describe("Optional fully-qualified class name to view source. Omit to list all classes.")
518
+ };
519
+ const decompileModJarSchema = z.object(decompileModJarShape);
520
+ const getModClassSourceShape = {
521
+ jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
522
+ className: nonEmptyString.describe("Fully-qualified class name (e.g. com.example.MyMixin)")
523
+ };
524
+ const getModClassSourceSchema = z.object(getModClassSourceShape);
498
525
  const MOD_SEARCH_TYPES = ["class", "method", "field", "content", "all"];
499
526
  const modSearchTypeSchema = z.enum(MOD_SEARCH_TYPES);
500
- const searchModSourceSchema = z.object({
501
- jarPath: nonEmptyString,
502
- query: nonEmptyString,
503
- searchType: modSearchTypeSchema.optional(),
504
- limit: optionalPositiveInt
505
- });
527
+ const searchModSourceShape = {
528
+ jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
529
+ query: nonEmptyString.describe("Search pattern (regex or literal string)"),
530
+ searchType: modSearchTypeSchema.optional().describe("class | method | field | content | all (default all)"),
531
+ limit: optionalPositiveInt.describe("Max results (default 50, max 200)")
532
+ };
533
+ const searchModSourceSchema = z.object(searchModSourceShape);
506
534
  const REMAP_TARGETS = ["yarn", "mojang"];
507
535
  const remapTargetSchema = z.enum(REMAP_TARGETS);
508
- const remapModJarSchema = z.object({
509
- inputJar: nonEmptyString,
510
- outputJar: optionalNonEmptyString,
511
- mcVersion: optionalNonEmptyString,
512
- targetMapping: remapTargetSchema
513
- });
536
+ const remapModJarShape = {
537
+ inputJar: nonEmptyString.describe("Path to the mod JAR file"),
538
+ outputJar: optionalNonEmptyString.describe("Output path for remapped JAR (auto-generated if omitted)"),
539
+ mcVersion: optionalNonEmptyString.describe("Minecraft version (auto-detected from mod metadata if omitted)"),
540
+ targetMapping: remapTargetSchema.describe("yarn | mojang")
541
+ };
542
+ const remapModJarSchema = z.object(remapModJarShape);
514
543
  const emptySchema = z.object({}).passthrough();
515
544
  function getServerVersionFromPackageJson() {
516
545
  try {
@@ -526,7 +555,7 @@ function getServerVersionFromPackageJson() {
526
555
  return "0.3.0";
527
556
  }
528
557
  const SERVER_VERSION = getServerVersionFromPackageJson();
529
- const server = new MCPServer({
558
+ const server = new McpServer({
530
559
  name: "@adhisang/minecraft-modding-mcp",
531
560
  version: SERVER_VERSION
532
561
  });
@@ -737,7 +766,7 @@ async function runTool(tool, rawInput, schema, action) {
737
766
  const parsedInput = schema.parse(rawInput);
738
767
  const payload = await action(parsedInput);
739
768
  const { result, warnings } = splitWarnings(payload);
740
- return object({
769
+ return objectResult({
741
770
  result,
742
771
  meta: {
743
772
  requestId,
@@ -779,7 +808,7 @@ async function runTool(tool, rawInput, schema, action) {
779
808
  reason: caughtError instanceof Error ? caughtError.message : String(caughtError)
780
809
  });
781
810
  }
782
- return object({
811
+ return objectResult({
783
812
  error: problem,
784
813
  meta: {
785
814
  requestId,
@@ -790,646 +819,211 @@ async function runTool(tool, rawInput, schema, action) {
790
819
  });
791
820
  }
792
821
  }
793
- server.tool({
794
- name: "list-versions",
795
- description: "List available Minecraft versions from Mojang manifest and locally cached version jars.",
796
- inputs: [
797
- { name: "includeSnapshots", type: "boolean", description: "default false" },
798
- { name: "limit", type: "number", description: "default 20, max 200" }
799
- ],
800
- annotations: {
801
- readOnlyHint: true
802
- }
803
- }, async (rawInput) => {
804
- return runTool("list-versions", rawInput, listVersionsSchema, async (input) => sourceService.listVersions({
805
- includeSnapshots: input.includeSnapshots,
806
- limit: input.limit
807
- }));
808
- });
809
- server.tool({
810
- name: "resolve-artifact",
811
- description: "Resolve source artifact from version, jar path, or Maven coordinate and return artifact metadata. For targetKind=jar, only <basename>-sources.jar is auto-adopted; other adjacent *-sources.jar files are informational.",
812
- inputs: [
813
- { name: "targetKind", type: "string", required: true, description: "version | jar | coordinate" },
814
- { name: "targetValue", type: "string", required: true },
815
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn" },
816
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" },
817
- { name: "allowDecompile", type: "boolean", description: "default true" }
818
- ],
819
- annotations: {
820
- readOnlyHint: true
821
- }
822
- }, async (rawInput) => {
823
- return runTool("resolve-artifact", rawInput, resolveArtifactSchema, async (input) => sourceService.resolveArtifact({
824
- target: {
825
- kind: input.targetKind,
826
- value: input.targetValue
827
- },
828
- mapping: input.mapping,
829
- sourcePriority: input.sourcePriority,
830
- allowDecompile: input.allowDecompile
831
- }));
832
- });
833
- server.tool({
834
- name: "get-class-source",
835
- description: "Get Java source for a class by artifactId or by resolving target (version/jar/coordinate), with optional line-range filtering.",
836
- inputs: [
837
- { name: "className", type: "string", required: true },
838
- { name: "artifactId", type: "string" },
839
- { name: "targetKind", type: "string", description: "version | jar | coordinate" },
840
- { name: "targetValue", type: "string" },
841
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn" },
842
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" },
843
- { name: "allowDecompile", type: "boolean", description: "default true" },
844
- { name: "startLine", type: "number" },
845
- { name: "endLine", type: "number" },
846
- { name: "maxLines", type: "number" }
847
- ],
848
- annotations: {
849
- readOnlyHint: true
850
- }
851
- }, async (rawInput) => {
852
- return runTool("get-class-source", rawInput, getClassSourceSchema, async (input) => sourceService.getClassSource({
853
- className: input.className,
854
- artifactId: input.artifactId,
855
- target: buildTarget(input.targetKind, input.targetValue),
856
- mapping: input.mapping,
857
- sourcePriority: input.sourcePriority,
858
- allowDecompile: input.allowDecompile,
859
- startLine: input.startLine,
860
- endLine: input.endLine,
861
- maxLines: input.maxLines
862
- }));
863
- });
864
- server.tool({
865
- name: "get-class-members",
866
- description: "Get fields/methods/constructors for one class from binary bytecode by artifactId or by resolving target (version/jar/coordinate).",
867
- inputs: [
868
- { name: "className", type: "string", required: true },
869
- { name: "artifactId", type: "string" },
870
- { name: "targetKind", type: "string", description: "version | jar | coordinate" },
871
- { name: "targetValue", type: "string" },
872
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn (default official)" },
873
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" },
874
- { name: "allowDecompile", type: "boolean", description: "default true" },
875
- { name: "access", type: "string", description: "public | all (default public)" },
876
- { name: "includeSynthetic", type: "boolean", description: "default false" },
877
- { name: "includeInherited", type: "boolean", description: "default false" },
878
- { name: "memberPattern", type: "string" },
879
- { name: "maxMembers", type: "number", description: "default 500, max 5000" }
880
- ],
881
- annotations: {
882
- readOnlyHint: true
883
- }
884
- }, async (rawInput) => {
885
- return runTool("get-class-members", rawInput, getClassMembersSchema, async (input) => sourceService.getClassMembers({
886
- className: input.className,
887
- artifactId: input.artifactId,
888
- target: buildTarget(input.targetKind, input.targetValue),
889
- mapping: input.mapping,
890
- sourcePriority: input.sourcePriority,
891
- allowDecompile: input.allowDecompile,
892
- access: input.access,
893
- includeSynthetic: input.includeSynthetic,
894
- includeInherited: input.includeInherited,
895
- memberPattern: input.memberPattern,
896
- maxMembers: input.maxMembers
897
- }));
898
- });
899
- server.tool({
900
- name: "search-class-source",
901
- description: "Search indexed class source files for one artifact with symbol/text/path intent and optional one-hop relation expansion.",
902
- inputs: [
903
- { name: "artifactId", type: "string", required: true },
904
- { name: "query", type: "string", required: true },
905
- { name: "intent", type: "string", description: "symbol | text | path" },
906
- { name: "match", type: "string", description: "exact | prefix | contains | regex" },
907
- { name: "packagePrefix", type: "string" },
908
- { name: "fileGlob", type: "string" },
909
- { name: "symbolKind", type: "string", description: "class | interface | enum | record | method | field" },
910
- { name: "snippetLines", type: "number", description: "default 8, clamp 1..80" },
911
- { name: "includeDefinition", type: "boolean", description: "default false" },
912
- { name: "includeOneHop", type: "boolean", description: "default false" },
913
- { name: "limit", type: "number", description: "default 20" },
914
- { name: "cursor", type: "string" }
915
- ],
916
- annotations: {
917
- readOnlyHint: true
918
- }
919
- }, async (rawInput) => {
920
- return runTool("search-class-source", rawInput, searchClassSourceSchema, async (input) => {
921
- const scope = input.packagePrefix || input.fileGlob || input.symbolKind
922
- ? {
923
- packagePrefix: input.packagePrefix,
924
- fileGlob: input.fileGlob,
925
- symbolKind: input.symbolKind
926
- }
927
- : undefined;
928
- const include = input.snippetLines !== undefined ||
929
- input.includeDefinition !== undefined ||
930
- input.includeOneHop !== undefined
931
- ? {
932
- snippetLines: input.snippetLines,
933
- includeDefinition: input.includeDefinition,
934
- includeOneHop: input.includeOneHop
935
- }
936
- : undefined;
937
- return sourceService.searchClassSource({
938
- artifactId: input.artifactId,
939
- query: input.query,
940
- intent: input.intent,
941
- match: input.match,
942
- scope: scope,
943
- include,
944
- limit: input.limit,
945
- cursor: input.cursor
946
- });
947
- });
948
- });
949
- server.tool({
950
- name: "get-artifact-file",
951
- description: "Get full source file content by artifactId and file path.",
952
- inputs: [
953
- { name: "artifactId", type: "string", required: true },
954
- { name: "filePath", type: "string", required: true },
955
- { name: "maxBytes", type: "number" }
956
- ],
957
- annotations: {
958
- readOnlyHint: true
959
- }
960
- }, async (rawInput) => {
961
- return runTool("get-artifact-file", rawInput, getArtifactFileSchema, async (input) => sourceService.getArtifactFile({
962
- artifactId: input.artifactId,
963
- filePath: input.filePath,
964
- maxBytes: input.maxBytes
965
- }));
966
- });
967
- server.tool({
968
- name: "list-artifact-files",
969
- description: "List source file paths in an artifact with optional prefix filter and cursor-based pagination.",
970
- inputs: [
971
- { name: "artifactId", type: "string", required: true },
972
- { name: "prefix", type: "string" },
973
- { name: "limit", type: "number" },
974
- { name: "cursor", type: "string" }
975
- ],
976
- annotations: {
977
- readOnlyHint: true
978
- }
979
- }, async (rawInput) => {
980
- return runTool("list-artifact-files", rawInput, listArtifactFilesSchema, async (input) => sourceService.listArtifactFiles(input));
981
- });
982
- server.tool({
983
- name: "trace-symbol-lifecycle",
984
- description: "Trace which Minecraft versions contain a specific class method and report first/last seen versions.",
985
- inputs: [
986
- { name: "symbol", type: "string", required: true, description: "fully.qualified.Class.method" },
987
- { name: "descriptor", type: "string", description: 'optional JVM descriptor, e.g. "(I)V"' },
988
- { name: "fromVersion", type: "string" },
989
- { name: "toVersion", type: "string" },
990
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn (default official)" },
991
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" },
992
- { name: "includeSnapshots", type: "boolean", description: "default false" },
993
- { name: "maxVersions", type: "number", description: "default 120, max 400" },
994
- { name: "includeTimeline", type: "boolean", description: "default false" }
995
- ],
996
- annotations: {
997
- readOnlyHint: true
998
- }
999
- }, async (rawInput) => {
1000
- return runTool("trace-symbol-lifecycle", rawInput, traceSymbolLifecycleSchema, async (input) => sourceService.traceSymbolLifecycle({
1001
- symbol: input.symbol,
1002
- descriptor: input.descriptor,
1003
- fromVersion: input.fromVersion,
1004
- toVersion: input.toVersion,
1005
- mapping: input.mapping,
1006
- sourcePriority: input.sourcePriority,
1007
- includeSnapshots: input.includeSnapshots,
1008
- maxVersions: input.maxVersions,
1009
- includeTimeline: input.includeTimeline
1010
- }));
1011
- });
1012
- server.tool({
1013
- name: "diff-class-signatures",
1014
- description: "Compare one class signature between two Minecraft versions and report added/removed/modified constructors, methods, and fields.",
1015
- inputs: [
1016
- { name: "className", type: "string", required: true },
1017
- { name: "fromVersion", type: "string", required: true },
1018
- { name: "toVersion", type: "string", required: true },
1019
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn (default official)" },
1020
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1021
- ],
1022
- annotations: {
1023
- readOnlyHint: true
1024
- }
1025
- }, async (rawInput) => {
1026
- return runTool("diff-class-signatures", rawInput, diffClassSignaturesSchema, async (input) => sourceService.diffClassSignatures({
1027
- className: input.className,
1028
- fromVersion: input.fromVersion,
1029
- toVersion: input.toVersion,
1030
- mapping: input.mapping,
1031
- sourcePriority: input.sourcePriority
1032
- }));
1033
- });
1034
- server.tool({
1035
- name: "find-mapping",
1036
- description: "Find symbol mapping candidates between namespaces using structured symbol inputs for a specific Minecraft version.",
1037
- inputs: [
1038
- { name: "version", type: "string", required: true },
1039
- { name: "kind", type: "string", required: true, description: "class | field | method" },
1040
- { name: "name", type: "string", required: true },
1041
- { name: "owner", type: "string" },
1042
- { name: "descriptor", type: "string" },
1043
- { name: "sourceMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1044
- { name: "targetMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1045
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1046
- ],
1047
- annotations: {
1048
- readOnlyHint: true
1049
- }
1050
- }, async (rawInput) => {
1051
- return runTool("find-mapping", rawInput, findMappingSchema, async (input) => sourceService.findMapping({
1052
- version: input.version,
1053
- kind: input.kind,
1054
- name: input.name,
1055
- owner: input.owner,
1056
- descriptor: input.descriptor,
1057
- sourceMapping: input.sourceMapping,
1058
- targetMapping: input.targetMapping,
1059
- sourcePriority: input.sourcePriority
1060
- }));
1061
- });
1062
- server.tool({
1063
- name: "resolve-method-mapping-exact",
1064
- description: "Resolve one method mapping exactly by owner+name+descriptor between namespaces and report resolved/not_found/ambiguous.",
1065
- inputs: [
1066
- { name: "version", type: "string", required: true },
1067
- { name: "kind", type: "string", required: true, description: "class | field | method" },
1068
- { name: "name", type: "string", required: true },
1069
- { name: "owner", type: "string" },
1070
- { name: "descriptor", type: "string", description: "required for kind=method" },
1071
- { name: "sourceMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1072
- { name: "targetMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1073
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1074
- ],
1075
- annotations: {
1076
- readOnlyHint: true
1077
- }
1078
- }, async (rawInput) => {
1079
- return runTool("resolve-method-mapping-exact", rawInput, resolveMethodMappingExactSchema, async (input) => sourceService.resolveMethodMappingExact({
1080
- version: input.version,
1081
- kind: input.kind,
1082
- name: input.name,
1083
- owner: input.owner,
1084
- descriptor: input.descriptor,
1085
- sourceMapping: input.sourceMapping,
1086
- targetMapping: input.targetMapping,
1087
- sourcePriority: input.sourcePriority
1088
- }));
1089
- });
1090
- server.tool({
1091
- name: "get-class-api-matrix",
1092
- description: "List class/member API rows across official/mojang/intermediary/yarn mappings for one class and Minecraft version.",
1093
- inputs: [
1094
- { name: "version", type: "string", required: true },
1095
- { name: "className", type: "string", required: true },
1096
- { name: "classNameMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1097
- { name: "includeKinds", type: "string", description: "comma-separated: class,field,method" },
1098
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1099
- ],
1100
- annotations: {
1101
- readOnlyHint: true
1102
- }
1103
- }, async (rawInput) => {
1104
- return runTool("get-class-api-matrix", rawInput, getClassApiMatrixSchema, async (input) => sourceService.getClassApiMatrix({
1105
- version: input.version,
1106
- className: input.className,
1107
- classNameMapping: input.classNameMapping,
1108
- includeKinds: parseClassApiKinds(input.includeKinds),
1109
- sourcePriority: input.sourcePriority
1110
- }));
1111
- });
1112
- server.tool({
1113
- name: "resolve-workspace-symbol",
1114
- description: "Resolve class/field/method names as seen at compile time for a workspace by reading Gradle Loom mapping settings.",
1115
- inputs: [
1116
- { name: "projectPath", type: "string", required: true },
1117
- { name: "version", type: "string", required: true },
1118
- { name: "kind", type: "string", required: true, description: "class | field | method" },
1119
- { name: "name", type: "string", required: true },
1120
- { name: "owner", type: "string" },
1121
- { name: "descriptor", type: "string" },
1122
- { name: "sourceMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1123
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1124
- ],
1125
- annotations: {
1126
- readOnlyHint: true
1127
- }
1128
- }, async (rawInput) => {
1129
- return runTool("resolve-workspace-symbol", rawInput, resolveWorkspaceSymbolSchema, async (input) => sourceService.resolveWorkspaceSymbol({
1130
- projectPath: input.projectPath,
1131
- version: input.version,
1132
- kind: input.kind,
1133
- name: input.name,
1134
- owner: input.owner,
1135
- descriptor: input.descriptor,
1136
- sourceMapping: input.sourceMapping,
1137
- sourcePriority: input.sourcePriority
1138
- }));
1139
- });
1140
- server.tool({
1141
- name: "check-symbol-exists",
1142
- description: "Check whether a class/field/method symbol exists in a specific mapping namespace for one Minecraft version.",
1143
- inputs: [
1144
- { name: "version", type: "string", required: true },
1145
- { name: "kind", type: "string", required: true, description: "class | field | method" },
1146
- { name: "owner", type: "string" },
1147
- { name: "name", type: "string", required: true },
1148
- { name: "descriptor", type: "string", description: "required for kind=method" },
1149
- { name: "sourceMapping", type: "string", required: true, description: "official | mojang | intermediary | yarn" },
1150
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1151
- ],
1152
- annotations: {
1153
- readOnlyHint: true
1154
- }
1155
- }, async (rawInput) => {
1156
- return runTool("check-symbol-exists", rawInput, checkSymbolExistsSchema, async (input) => sourceService.checkSymbolExists({
1157
- version: input.version,
1158
- kind: input.kind,
1159
- owner: input.owner,
1160
- name: input.name,
1161
- descriptor: input.descriptor,
1162
- sourceMapping: input.sourceMapping,
1163
- sourcePriority: input.sourcePriority
1164
- }));
1165
- });
1166
- server.tool({
1167
- name: "nbt-to-json",
1168
- description: "Decode Java Edition NBT binary payload (base64) into typed JSON.",
1169
- inputs: [
1170
- { name: "nbtBase64", type: "string", required: true },
1171
- { name: "compression", type: "string", description: "none | gzip | auto (default auto)" }
1172
- ],
1173
- annotations: {
1174
- readOnlyHint: true
1175
- }
1176
- }, async (rawInput) => {
1177
- return runTool("nbt-to-json", rawInput, nbtToJsonSchema, async (input) => Promise.resolve(nbtBase64ToTypedJson({
1178
- nbtBase64: input.nbtBase64,
1179
- compression: input.compression
1180
- }, nbtLimits)));
1181
- });
1182
- server.tool({
1183
- name: "nbt-apply-json-patch",
1184
- description: "Apply RFC6902 add/remove/replace/test operations to typed NBT JSON.",
1185
- inputs: [
1186
- { name: "typedJson", type: "object", required: true },
1187
- {
1188
- name: "patch",
1189
- type: "array",
1190
- required: true,
1191
- description: "RFC6902 operation array (add/remove/replace/test)"
1192
- }
1193
- ],
1194
- annotations: {
1195
- readOnlyHint: true
1196
- }
1197
- }, async (rawInput) => {
1198
- return runTool("nbt-apply-json-patch", rawInput, nbtApplyJsonPatchSchema, async (input) => Promise.resolve(applyNbtJsonPatch({
1199
- typedJson: input.typedJson,
1200
- patch: input.patch
1201
- }, nbtLimits)));
1202
- });
1203
- server.tool({
1204
- name: "json-to-nbt",
1205
- description: "Encode typed NBT JSON to Java Edition NBT binary payload (base64).",
1206
- inputs: [
1207
- { name: "typedJson", type: "object", required: true },
1208
- { name: "compression", type: "string", description: "none | gzip (default none)" }
1209
- ],
1210
- annotations: {
1211
- readOnlyHint: true
1212
- }
1213
- }, async (rawInput) => {
1214
- return runTool("json-to-nbt", rawInput, jsonToNbtSchema, async (input) => Promise.resolve(typedJsonToNbtBase64({
1215
- typedJson: input.typedJson,
1216
- compression: input.compression
1217
- }, nbtLimits)));
1218
- });
1219
- server.tool({
1220
- name: "index-artifact",
1221
- description: "Rebuild indexed files/symbols metadata for an existing artifactId. Does not resolve new artifacts.",
1222
- inputs: [
1223
- { name: "artifactId", type: "string", required: true },
1224
- { name: "force", type: "boolean", description: "default false" }
1225
- ]
1226
- }, async (rawInput) => {
1227
- return runTool("index-artifact", rawInput, indexArtifactSchema, async (input) => sourceService.indexArtifact({
1228
- artifactId: input.artifactId,
1229
- force: input.force
1230
- }));
1231
- });
1232
- server.tool({
1233
- name: "get-runtime-metrics",
1234
- description: "Get runtime service counters and latency snapshots for cache/search/index diagnostics.",
1235
- annotations: {
1236
- readOnlyHint: true
1237
- }
1238
- }, async (rawInput) => {
1239
- return runTool("get-runtime-metrics", rawInput, emptySchema, async () => Promise.resolve(sourceService.getRuntimeMetrics()));
1240
- });
1241
- server.tool({
1242
- name: "validate-mixin",
1243
- description: "Validate Mixin source against Minecraft bytecode signatures for a given version.",
1244
- inputs: [
1245
- { name: "source", type: "string", required: true, description: "Mixin Java source text" },
1246
- { name: "version", type: "string", required: true, description: "Minecraft version" },
1247
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn" },
1248
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1249
- ],
1250
- annotations: {
1251
- readOnlyHint: true
1252
- }
1253
- }, async (rawInput) => {
1254
- return runTool("validate-mixin", rawInput, validateMixinSchema, async (input) => sourceService.validateMixin({
1255
- source: input.source,
1256
- version: input.version,
1257
- mapping: input.mapping,
1258
- sourcePriority: input.sourcePriority
1259
- }));
1260
- });
1261
- server.tool({
1262
- name: "validate-access-widener",
1263
- description: "Validate Access Widener file entries against Minecraft bytecode signatures for a given version.",
1264
- inputs: [
1265
- { name: "content", type: "string", required: true, description: "Access Widener file content" },
1266
- { name: "version", type: "string", required: true, description: "Minecraft version" },
1267
- { name: "mapping", type: "string", description: "official | mojang | intermediary | yarn" },
1268
- { name: "sourcePriority", type: "string", description: "loom-first | maven-first" }
1269
- ],
1270
- annotations: {
1271
- readOnlyHint: true
1272
- }
1273
- }, async (rawInput) => {
1274
- return runTool("validate-access-widener", rawInput, validateAccessWidenerSchema, async (input) => sourceService.validateAccessWidener({
1275
- content: input.content,
1276
- version: input.version,
1277
- mapping: input.mapping,
1278
- sourcePriority: input.sourcePriority
1279
- }));
1280
- });
1281
- server.tool({
1282
- name: "analyze-mod-jar",
1283
- description: "Analyze a Minecraft mod JAR to extract loader type, metadata, entrypoints, mixins, and dependencies.",
1284
- inputs: [
1285
- { name: "jarPath", type: "string", required: true, description: "Local path to the mod JAR file" },
1286
- { name: "includeClasses", type: "boolean", description: "Include full class listing (default false)" }
1287
- ],
1288
- annotations: {
1289
- readOnlyHint: true
1290
- }
1291
- }, async (rawInput) => {
1292
- return runTool("analyze-mod-jar", rawInput, analyzeModJarSchema, async (input) => {
1293
- const result = await analyzeModJar(input.jarPath, {
1294
- includeClasses: input.includeClasses ?? false
1295
- });
1296
- return result;
1297
- });
1298
- });
1299
- server.tool({
1300
- name: "get-registry-data",
1301
- description: "Get Minecraft registry data (blocks, items, biomes, etc.) for a specific version by running the server data generator.",
1302
- inputs: [
1303
- { name: "version", type: "string", required: true, description: "Minecraft version (e.g. 1.21)" },
1304
- {
1305
- name: "registry",
1306
- type: "string",
1307
- description: 'Optional registry name (e.g. "block", "item", "minecraft:biome"). Omit to list all registries.'
822
+ 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({
823
+ includeSnapshots: input.includeSnapshots,
824
+ limit: input.limit
825
+ })));
826
+ server.tool("resolve-artifact", "Resolve source artifact from version, jar path, or Maven coordinate and return artifact metadata. For targetKind=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({
827
+ target: {
828
+ kind: input.targetKind,
829
+ value: input.targetValue
830
+ },
831
+ mapping: input.mapping,
832
+ sourcePriority: input.sourcePriority,
833
+ allowDecompile: input.allowDecompile
834
+ })));
835
+ server.tool("get-class-source", "Get Java source for a class by artifactId or by resolving target (version/jar/coordinate), with optional line-range filtering.", getClassSourceShape, { readOnlyHint: true }, async (args) => runTool("get-class-source", args, getClassSourceSchema, async (input) => sourceService.getClassSource({
836
+ className: input.className,
837
+ artifactId: input.artifactId,
838
+ target: buildTarget(input.targetKind, input.targetValue),
839
+ mapping: input.mapping,
840
+ sourcePriority: input.sourcePriority,
841
+ allowDecompile: input.allowDecompile,
842
+ startLine: input.startLine,
843
+ endLine: input.endLine,
844
+ maxLines: input.maxLines
845
+ })));
846
+ server.tool("get-class-members", "Get fields/methods/constructors for one class from binary bytecode by artifactId or by resolving target (version/jar/coordinate).", getClassMembersShape, { readOnlyHint: true }, async (args) => runTool("get-class-members", args, getClassMembersSchema, async (input) => sourceService.getClassMembers({
847
+ className: input.className,
848
+ artifactId: input.artifactId,
849
+ target: buildTarget(input.targetKind, input.targetValue),
850
+ mapping: input.mapping,
851
+ sourcePriority: input.sourcePriority,
852
+ allowDecompile: input.allowDecompile,
853
+ access: input.access,
854
+ includeSynthetic: input.includeSynthetic,
855
+ includeInherited: input.includeInherited,
856
+ memberPattern: input.memberPattern,
857
+ maxMembers: input.maxMembers
858
+ })));
859
+ server.tool("search-class-source", "Search indexed class source files for one artifact with symbol/text/path intent and optional one-hop relation expansion.", searchClassSourceShape, { readOnlyHint: true }, async (args) => runTool("search-class-source", args, searchClassSourceSchema, async (input) => {
860
+ const scope = input.packagePrefix || input.fileGlob || input.symbolKind
861
+ ? {
862
+ packagePrefix: input.packagePrefix,
863
+ fileGlob: input.fileGlob,
864
+ symbolKind: input.symbolKind
1308
865
  }
1309
- ],
1310
- annotations: {
1311
- readOnlyHint: true
1312
- }
1313
- }, async (rawInput) => {
1314
- return runTool("get-registry-data", rawInput, getRegistryDataSchema, async (input) => sourceService.getRegistryData({
1315
- version: input.version,
1316
- registry: input.registry
1317
- }));
1318
- });
1319
- server.tool({
1320
- name: "compare-versions",
1321
- description: "Compare two Minecraft versions to find added/removed classes and registry entry changes. Useful for understanding what changed between versions during mod migration.",
1322
- inputs: [
1323
- { name: "fromVersion", type: "string", required: true, description: "Older Minecraft version (e.g. 1.20.4)" },
1324
- { name: "toVersion", type: "string", required: true, description: "Newer Minecraft version (e.g. 1.21)" },
1325
- {
1326
- name: "category",
1327
- type: "string",
1328
- description: "classes | registry | all (default all)"
1329
- },
1330
- { name: "packageFilter", type: "string", description: "Filter classes to a package prefix (e.g. net.minecraft.world.item)" },
1331
- { name: "maxClassResults", type: "number", description: "Max class results per direction (default 500, max 5000)" }
1332
- ],
1333
- annotations: {
1334
- readOnlyHint: true
1335
- }
1336
- }, async (rawInput) => {
1337
- return runTool("compare-versions", rawInput, compareVersionsSchema, async (input) => sourceService.compareVersions({
1338
- fromVersion: input.fromVersion,
1339
- toVersion: input.toVersion,
1340
- category: input.category,
1341
- packageFilter: input.packageFilter,
1342
- maxClassResults: input.maxClassResults
1343
- }));
1344
- });
1345
- server.tool({
1346
- name: "decompile-mod-jar",
1347
- description: "Decompile a Minecraft mod JAR using Vineflower and list available classes, or view a specific class source. Builds on analyze-mod-jar by exposing the actual source code.",
1348
- inputs: [
1349
- { name: "jarPath", type: "string", required: true, description: "Local path to the mod JAR file" },
1350
- {
1351
- name: "className",
1352
- type: "string",
1353
- description: "Optional fully-qualified class name to view source. Omit to list all classes."
866
+ : undefined;
867
+ const include = input.snippetLines !== undefined ||
868
+ input.includeDefinition !== undefined ||
869
+ input.includeOneHop !== undefined
870
+ ? {
871
+ snippetLines: input.snippetLines,
872
+ includeDefinition: input.includeDefinition,
873
+ includeOneHop: input.includeOneHop
1354
874
  }
1355
- ],
1356
- annotations: {
1357
- readOnlyHint: true
1358
- }
1359
- }, async (rawInput) => {
1360
- return runTool("decompile-mod-jar", rawInput, decompileModJarSchema, async (input) => sourceService.decompileModJar({
1361
- jarPath: input.jarPath,
1362
- className: input.className
1363
- }));
1364
- });
1365
- server.tool({
1366
- name: "get-mod-class-source",
1367
- description: "Get decompiled source code for a specific class in a mod JAR. The mod JAR will be decompiled if not already cached.",
1368
- inputs: [
1369
- { name: "jarPath", type: "string", required: true, description: "Local path to the mod JAR file" },
1370
- { name: "className", type: "string", required: true, description: "Fully-qualified class name (e.g. com.example.MyMixin)" }
1371
- ],
1372
- annotations: {
1373
- readOnlyHint: true
1374
- }
1375
- }, async (rawInput) => {
1376
- return runTool("get-mod-class-source", rawInput, getModClassSourceSchema, async (input) => sourceService.getModClassSource({
1377
- jarPath: input.jarPath,
1378
- className: input.className
1379
- }));
1380
- });
1381
- server.tool({
1382
- name: "search-mod-source",
1383
- description: "Search through decompiled mod JAR source code by class name, method, field, or content pattern. The mod JAR will be decompiled automatically if not already cached.",
1384
- inputs: [
1385
- { name: "jarPath", type: "string", required: true, description: "Local path to the mod JAR file" },
1386
- { name: "query", type: "string", required: true, description: "Search pattern (regex or literal string)" },
1387
- {
1388
- name: "searchType",
1389
- type: "string",
1390
- description: "class | method | field | content | all (default all)"
1391
- },
1392
- { name: "limit", type: "number", description: "Max results (default 50, max 200)" }
1393
- ],
1394
- annotations: {
1395
- readOnlyHint: true
1396
- }
1397
- }, async (rawInput) => {
1398
- return runTool("search-mod-source", rawInput, searchModSourceSchema, async (input) => sourceService.searchModSource({
1399
- jarPath: input.jarPath,
875
+ : undefined;
876
+ return sourceService.searchClassSource({
877
+ artifactId: input.artifactId,
1400
878
  query: input.query,
1401
- searchType: input.searchType,
1402
- limit: input.limit
1403
- }));
1404
- });
1405
- server.tool({
1406
- name: "remap-mod-jar",
1407
- description: "Remap a Fabric mod JAR from intermediary to yarn/mojang names. Requires Java to be installed.",
1408
- inputs: [
1409
- { name: "inputJar", type: "string", required: true, description: "Path to the mod JAR file" },
1410
- { name: "outputJar", type: "string", description: "Output path for remapped JAR (auto-generated if omitted)" },
1411
- {
1412
- name: "mcVersion",
1413
- type: "string",
1414
- description: "Minecraft version (auto-detected from mod metadata if omitted)"
1415
- },
1416
- { name: "targetMapping", type: "string", required: true, description: "yarn | mojang" }
1417
- ],
1418
- annotations: {
1419
- readOnlyHint: false
1420
- }
1421
- }, async (rawInput) => {
1422
- return runTool("remap-mod-jar", rawInput, remapModJarSchema, async (input) => {
1423
- const result = await remapModJar({
1424
- inputJar: input.inputJar,
1425
- outputJar: input.outputJar,
1426
- mcVersion: input.mcVersion,
1427
- targetMapping: input.targetMapping
1428
- }, config);
1429
- return result;
879
+ intent: input.intent,
880
+ match: input.match,
881
+ scope: scope,
882
+ include,
883
+ limit: input.limit,
884
+ cursor: input.cursor
1430
885
  });
1431
- });
1432
- export function startServer() {
886
+ }));
887
+ server.tool("get-artifact-file", "Get full source file content by artifactId and file path.", getArtifactFileShape, { readOnlyHint: true }, async (args) => runTool("get-artifact-file", args, getArtifactFileSchema, async (input) => sourceService.getArtifactFile({
888
+ artifactId: input.artifactId,
889
+ filePath: input.filePath,
890
+ maxBytes: input.maxBytes
891
+ })));
892
+ server.tool("list-artifact-files", "List source file paths in an artifact with optional prefix filter and cursor-based pagination.", listArtifactFilesShape, { readOnlyHint: true }, async (args) => runTool("list-artifact-files", args, listArtifactFilesSchema, async (input) => sourceService.listArtifactFiles(input)));
893
+ server.tool("trace-symbol-lifecycle", "Trace which Minecraft versions contain a specific class method and report first/last seen versions.", traceSymbolLifecycleShape, { readOnlyHint: true }, async (args) => runTool("trace-symbol-lifecycle", args, traceSymbolLifecycleSchema, async (input) => sourceService.traceSymbolLifecycle({
894
+ symbol: input.symbol,
895
+ descriptor: input.descriptor,
896
+ fromVersion: input.fromVersion,
897
+ toVersion: input.toVersion,
898
+ mapping: input.mapping,
899
+ sourcePriority: input.sourcePriority,
900
+ includeSnapshots: input.includeSnapshots,
901
+ maxVersions: input.maxVersions,
902
+ includeTimeline: input.includeTimeline
903
+ })));
904
+ server.tool("diff-class-signatures", "Compare one class signature between two Minecraft versions and report added/removed/modified constructors, methods, and fields.", diffClassSignaturesShape, { readOnlyHint: true }, async (args) => runTool("diff-class-signatures", args, diffClassSignaturesSchema, async (input) => sourceService.diffClassSignatures({
905
+ className: input.className,
906
+ fromVersion: input.fromVersion,
907
+ toVersion: input.toVersion,
908
+ mapping: input.mapping,
909
+ sourcePriority: input.sourcePriority
910
+ })));
911
+ server.tool("find-mapping", "Find symbol mapping candidates between namespaces using structured symbol inputs for a specific Minecraft version.", findMappingShape, { readOnlyHint: true }, async (args) => runTool("find-mapping", args, findMappingSchema, async (input) => sourceService.findMapping({
912
+ version: input.version,
913
+ kind: input.kind,
914
+ name: input.name,
915
+ owner: input.owner,
916
+ descriptor: input.descriptor,
917
+ sourceMapping: input.sourceMapping,
918
+ targetMapping: input.targetMapping,
919
+ sourcePriority: input.sourcePriority
920
+ })));
921
+ 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({
922
+ version: input.version,
923
+ kind: input.kind,
924
+ name: input.name,
925
+ owner: input.owner,
926
+ descriptor: input.descriptor,
927
+ sourceMapping: input.sourceMapping,
928
+ targetMapping: input.targetMapping,
929
+ sourcePriority: input.sourcePriority
930
+ })));
931
+ server.tool("get-class-api-matrix", "List class/member API rows across official/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({
932
+ version: input.version,
933
+ className: input.className,
934
+ classNameMapping: input.classNameMapping,
935
+ includeKinds: parseClassApiKinds(input.includeKinds),
936
+ sourcePriority: input.sourcePriority
937
+ })));
938
+ server.tool("resolve-workspace-symbol", "Resolve class/field/method names as seen at compile time for a workspace by reading Gradle Loom mapping settings.", resolveWorkspaceSymbolShape, { readOnlyHint: true }, async (args) => runTool("resolve-workspace-symbol", args, resolveWorkspaceSymbolSchema, async (input) => sourceService.resolveWorkspaceSymbol({
939
+ projectPath: input.projectPath,
940
+ version: input.version,
941
+ kind: input.kind,
942
+ name: input.name,
943
+ owner: input.owner,
944
+ descriptor: input.descriptor,
945
+ sourceMapping: input.sourceMapping,
946
+ sourcePriority: input.sourcePriority
947
+ })));
948
+ server.tool("check-symbol-exists", "Check whether a class/field/method symbol exists in a specific mapping namespace for one Minecraft version.", checkSymbolExistsShape, { readOnlyHint: true }, async (args) => runTool("check-symbol-exists", args, checkSymbolExistsSchema, async (input) => sourceService.checkSymbolExists({
949
+ version: input.version,
950
+ kind: input.kind,
951
+ owner: input.owner,
952
+ name: input.name,
953
+ descriptor: input.descriptor,
954
+ sourceMapping: input.sourceMapping,
955
+ sourcePriority: input.sourcePriority
956
+ })));
957
+ server.tool("nbt-to-json", "Decode Java Edition NBT binary payload (base64) into typed JSON.", nbtToJsonShape, { readOnlyHint: true }, async (args) => runTool("nbt-to-json", args, nbtToJsonSchema, async (input) => Promise.resolve(nbtBase64ToTypedJson({
958
+ nbtBase64: input.nbtBase64,
959
+ compression: input.compression
960
+ }, nbtLimits))));
961
+ server.tool("nbt-apply-json-patch", "Apply RFC6902 add/remove/replace/test operations to typed NBT JSON.", nbtApplyJsonPatchShape, { readOnlyHint: true }, async (args) => runTool("nbt-apply-json-patch", args, nbtApplyJsonPatchSchema, async (input) => Promise.resolve(applyNbtJsonPatch({
962
+ typedJson: input.typedJson,
963
+ patch: input.patch
964
+ }, nbtLimits))));
965
+ server.tool("json-to-nbt", "Encode typed NBT JSON to Java Edition NBT binary payload (base64).", jsonToNbtShape, { readOnlyHint: true }, async (args) => runTool("json-to-nbt", args, jsonToNbtSchema, async (input) => Promise.resolve(typedJsonToNbtBase64({
966
+ typedJson: input.typedJson,
967
+ compression: input.compression
968
+ }, nbtLimits))));
969
+ server.tool("index-artifact", "Rebuild indexed files/symbols metadata for an existing artifactId. Does not resolve new artifacts.", indexArtifactShape, async (args) => runTool("index-artifact", args, indexArtifactSchema, async (input) => sourceService.indexArtifact({
970
+ artifactId: input.artifactId,
971
+ force: input.force
972
+ })));
973
+ 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())));
974
+ 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({
975
+ source: input.source,
976
+ version: input.version,
977
+ mapping: input.mapping,
978
+ sourcePriority: input.sourcePriority
979
+ })));
980
+ server.tool("validate-access-widener", "Validate Access Widener file entries against Minecraft bytecode signatures for a given version.", validateAccessWidenerShape, { readOnlyHint: true }, async (args) => runTool("validate-access-widener", args, validateAccessWidenerSchema, async (input) => sourceService.validateAccessWidener({
981
+ content: input.content,
982
+ version: input.version,
983
+ mapping: input.mapping,
984
+ sourcePriority: input.sourcePriority
985
+ })));
986
+ server.tool("analyze-mod-jar", "Analyze a Minecraft mod JAR to extract loader type, metadata, entrypoints, mixins, and dependencies.", analyzeModJarShape, { readOnlyHint: true }, async (args) => runTool("analyze-mod-jar", args, analyzeModJarSchema, async (input) => {
987
+ const result = await analyzeModJar(input.jarPath, {
988
+ includeClasses: input.includeClasses ?? false
989
+ });
990
+ return result;
991
+ }));
992
+ server.tool("get-registry-data", "Get Minecraft registry data (blocks, items, biomes, etc.) for a specific version by running the server data generator.", getRegistryDataShape, { readOnlyHint: true }, async (args) => runTool("get-registry-data", args, getRegistryDataSchema, async (input) => sourceService.getRegistryData({
993
+ version: input.version,
994
+ registry: input.registry
995
+ })));
996
+ server.tool("compare-versions", "Compare two Minecraft versions to find added/removed classes and registry entry changes. Useful for understanding what changed between versions during mod migration.", compareVersionsShape, { readOnlyHint: true }, async (args) => runTool("compare-versions", args, compareVersionsSchema, async (input) => sourceService.compareVersions({
997
+ fromVersion: input.fromVersion,
998
+ toVersion: input.toVersion,
999
+ category: input.category,
1000
+ packageFilter: input.packageFilter,
1001
+ maxClassResults: input.maxClassResults
1002
+ })));
1003
+ server.tool("decompile-mod-jar", "Decompile a Minecraft mod JAR using Vineflower and list available classes, or view a specific class source. Builds on analyze-mod-jar by exposing the actual source code.", decompileModJarShape, { readOnlyHint: true }, async (args) => runTool("decompile-mod-jar", args, decompileModJarSchema, async (input) => sourceService.decompileModJar({
1004
+ jarPath: input.jarPath,
1005
+ className: input.className
1006
+ })));
1007
+ server.tool("get-mod-class-source", "Get decompiled source code for a specific class in a mod JAR. The mod JAR will be decompiled if not already cached.", getModClassSourceShape, { readOnlyHint: true }, async (args) => runTool("get-mod-class-source", args, getModClassSourceSchema, async (input) => sourceService.getModClassSource({
1008
+ jarPath: input.jarPath,
1009
+ className: input.className
1010
+ })));
1011
+ server.tool("search-mod-source", "Search through decompiled mod JAR source code by class name, method, field, or content pattern. The mod JAR will be decompiled automatically if not already cached.", searchModSourceShape, { readOnlyHint: true }, async (args) => runTool("search-mod-source", args, searchModSourceSchema, async (input) => sourceService.searchModSource({
1012
+ jarPath: input.jarPath,
1013
+ query: input.query,
1014
+ searchType: input.searchType,
1015
+ limit: input.limit
1016
+ })));
1017
+ server.tool("remap-mod-jar", "Remap a Fabric mod JAR from intermediary to yarn/mojang names. Requires Java to be installed.", remapModJarShape, { readOnlyHint: false }, async (args) => runTool("remap-mod-jar", args, remapModJarSchema, async (input) => {
1018
+ const result = await remapModJar({
1019
+ inputJar: input.inputJar,
1020
+ outputJar: input.outputJar,
1021
+ mcVersion: input.mcVersion,
1022
+ targetMapping: input.targetMapping
1023
+ }, config);
1024
+ return result;
1025
+ }));
1026
+ export async function startServer() {
1433
1027
  if (serverStarted) {
1434
1028
  return;
1435
1029
  }
@@ -1440,7 +1034,10 @@ export function startServer() {
1440
1034
  sqlitePath: config.sqlitePath,
1441
1035
  sourceRepos: config.sourceRepos.length
1442
1036
  });
1443
- server.listen();
1037
+ const transport = new CompatStdioServerTransport();
1038
+ await server.connect(transport);
1039
+ // In stdio mode, explicitly resume stdin so JSON-RPC lines are consumed.
1040
+ process.stdin.resume();
1444
1041
  serverStarted = true;
1445
1042
  }
1446
1043
  export { server, sourceService, config, SERVER_VERSION };