@adhisang/minecraft-modding-mcp 3.0.0 → 3.1.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.
@@ -3,12 +3,19 @@ export interface MetricTimingSnapshot {
3
3
  totalMs: number;
4
4
  avgMs: number;
5
5
  lastMs: number;
6
+ p95Ms: number;
7
+ p99Ms: number;
6
8
  }
7
9
  export interface CacheArtifactByteAccountingRow {
8
10
  artifact_id: string;
9
11
  content_bytes: number;
10
12
  updated_at: string;
11
13
  }
14
+ type CacheArtifactByteAccountingRefRow = {
15
+ artifactId: string;
16
+ totalContentBytes: number;
17
+ updatedAt: string;
18
+ };
12
19
  export interface RuntimeMetricSnapshot {
13
20
  resolve_duration_ms: MetricTimingSnapshot;
14
21
  search_duration_ms: MetricTimingSnapshot;
@@ -18,6 +25,10 @@ export interface RuntimeMetricSnapshot {
18
25
  search_intent_symbol_duration_ms: MetricTimingSnapshot;
19
26
  search_intent_text_duration_ms: MetricTimingSnapshot;
20
27
  search_intent_path_duration_ms: MetricTimingSnapshot;
28
+ search_query_mode_auto_count: number;
29
+ search_query_mode_token_count: number;
30
+ search_query_mode_literal_count: number;
31
+ search_literal_explicit_count: number;
21
32
  search_regex_fallback_count: number;
22
33
  search_token_bytes_returned: number;
23
34
  onehop_expand_count: number;
@@ -43,6 +54,10 @@ export declare class RuntimeMetrics {
43
54
  private cacheHits;
44
55
  private cacheMisses;
45
56
  private repoFailoverCount;
57
+ private searchQueryModeAutoCount;
58
+ private searchQueryModeTokenCount;
59
+ private searchQueryModeLiteralCount;
60
+ private searchLiteralExplicitCount;
46
61
  private searchRegexFallbackCount;
47
62
  private searchTokenBytesReturned;
48
63
  private oneHopExpandCount;
@@ -58,12 +73,13 @@ export declare class RuntimeMetrics {
58
73
  private cacheEvictions;
59
74
  private cacheEntries;
60
75
  private cacheTotalContentBytes;
61
- private cacheArtifactBytesLru;
76
+ private cacheArtifactBytesLruRef;
62
77
  constructor();
63
78
  recordDuration(name: DurationMetricName, durationMs: number): void;
64
79
  recordArtifactCacheHit(): void;
65
80
  recordArtifactCacheMiss(): void;
66
81
  recordRepoFailover(): void;
82
+ recordSearchQueryMode(mode: "auto" | "token" | "literal"): void;
67
83
  recordSearchIntentDuration(intent: "symbol" | "text" | "path", durationMs: number): void;
68
84
  recordSearchRegexFallback(): void;
69
85
  recordSearchTokenBytesReturned(tokenBytes: number): void;
@@ -80,7 +96,7 @@ export declare class RuntimeMetrics {
80
96
  recordCacheEviction(count?: number): void;
81
97
  setCacheEntries(entries: number): void;
82
98
  setCacheTotalContentBytes(totalBytes: number): void;
83
- setCacheArtifactByteAccounting(entries: CacheArtifactByteAccountingRow[]): void;
99
+ setCacheArtifactByteAccountingRef(entries: ReadonlyArray<CacheArtifactByteAccountingRefRow>): void;
84
100
  snapshot(): RuntimeMetricSnapshot;
85
101
  private toSnapshot;
86
102
  private resolveCacheHitRate;
@@ -1,8 +1,21 @@
1
+ const MAX_TIMING_SAMPLES = 512;
2
+ function percentile(samples, p) {
3
+ if (samples.length === 0) {
4
+ return 0;
5
+ }
6
+ const sorted = [...samples].sort((left, right) => left - right);
7
+ const index = Math.min(sorted.length - 1, Math.ceil((p / 100) * sorted.length) - 1);
8
+ return sorted[index] ?? 0;
9
+ }
1
10
  export class RuntimeMetrics {
2
11
  timings = new Map();
3
12
  cacheHits = 0;
4
13
  cacheMisses = 0;
5
14
  repoFailoverCount = 0;
15
+ searchQueryModeAutoCount = 0;
16
+ searchQueryModeTokenCount = 0;
17
+ searchQueryModeLiteralCount = 0;
18
+ searchLiteralExplicitCount = 0;
6
19
  searchRegexFallbackCount = 0;
7
20
  searchTokenBytesReturned = 0;
8
21
  oneHopExpandCount = 0;
@@ -18,7 +31,7 @@ export class RuntimeMetrics {
18
31
  cacheEvictions = 0;
19
32
  cacheEntries = 0;
20
33
  cacheTotalContentBytes = 0;
21
- cacheArtifactBytesLru = [];
34
+ cacheArtifactBytesLruRef = [];
22
35
  constructor() {
23
36
  const names = [
24
37
  "resolve_duration_ms",
@@ -31,7 +44,7 @@ export class RuntimeMetrics {
31
44
  "search_intent_path_duration_ms"
32
45
  ];
33
46
  for (const name of names) {
34
- this.timings.set(name, { count: 0, totalMs: 0, lastMs: 0 });
47
+ this.timings.set(name, { count: 0, totalMs: 0, lastMs: 0, samples: [] });
35
48
  }
36
49
  }
37
50
  recordDuration(name, durationMs) {
@@ -43,6 +56,10 @@ export class RuntimeMetrics {
43
56
  timing.count += 1;
44
57
  timing.totalMs += normalizedDuration;
45
58
  timing.lastMs = normalizedDuration;
59
+ timing.samples.push(normalizedDuration);
60
+ if (timing.samples.length > MAX_TIMING_SAMPLES) {
61
+ timing.samples.shift();
62
+ }
46
63
  }
47
64
  recordArtifactCacheHit() {
48
65
  this.cacheHits += 1;
@@ -53,6 +70,20 @@ export class RuntimeMetrics {
53
70
  recordRepoFailover() {
54
71
  this.repoFailoverCount += 1;
55
72
  }
73
+ recordSearchQueryMode(mode) {
74
+ switch (mode) {
75
+ case "auto":
76
+ this.searchQueryModeAutoCount += 1;
77
+ break;
78
+ case "token":
79
+ this.searchQueryModeTokenCount += 1;
80
+ break;
81
+ case "literal":
82
+ this.searchQueryModeLiteralCount += 1;
83
+ this.searchLiteralExplicitCount += 1;
84
+ break;
85
+ }
86
+ }
56
87
  recordSearchIntentDuration(intent, durationMs) {
57
88
  const metricName = intent === "symbol"
58
89
  ? "search_intent_symbol_duration_ms"
@@ -106,12 +137,8 @@ export class RuntimeMetrics {
106
137
  setCacheTotalContentBytes(totalBytes) {
107
138
  this.cacheTotalContentBytes = Math.max(0, Math.trunc(totalBytes));
108
139
  }
109
- setCacheArtifactByteAccounting(entries) {
110
- this.cacheArtifactBytesLru = entries.map((entry) => ({
111
- artifact_id: entry.artifact_id,
112
- content_bytes: Math.max(0, Math.trunc(entry.content_bytes)),
113
- updated_at: entry.updated_at
114
- }));
140
+ setCacheArtifactByteAccountingRef(entries) {
141
+ this.cacheArtifactBytesLruRef = entries;
115
142
  }
116
143
  snapshot() {
117
144
  return {
@@ -123,6 +150,10 @@ export class RuntimeMetrics {
123
150
  search_intent_symbol_duration_ms: this.toSnapshot("search_intent_symbol_duration_ms"),
124
151
  search_intent_text_duration_ms: this.toSnapshot("search_intent_text_duration_ms"),
125
152
  search_intent_path_duration_ms: this.toSnapshot("search_intent_path_duration_ms"),
153
+ search_query_mode_auto_count: this.searchQueryModeAutoCount,
154
+ search_query_mode_token_count: this.searchQueryModeTokenCount,
155
+ search_query_mode_literal_count: this.searchQueryModeLiteralCount,
156
+ search_literal_explicit_count: this.searchLiteralExplicitCount,
126
157
  search_regex_fallback_count: this.searchRegexFallbackCount,
127
158
  search_token_bytes_returned: this.searchTokenBytesReturned,
128
159
  onehop_expand_count: this.oneHopExpandCount,
@@ -138,7 +169,11 @@ export class RuntimeMetrics {
138
169
  cache_evictions: this.cacheEvictions,
139
170
  cache_entries: this.cacheEntries,
140
171
  cache_total_content_bytes: this.cacheTotalContentBytes,
141
- cache_artifact_bytes_lru: this.cacheArtifactBytesLru,
172
+ cache_artifact_bytes_lru: this.cacheArtifactBytesLruRef.map((entry) => ({
173
+ artifact_id: entry.artifactId,
174
+ content_bytes: Math.max(0, Math.trunc(entry.totalContentBytes)),
175
+ updated_at: entry.updatedAt
176
+ })),
142
177
  cache_hit_rate: this.resolveCacheHitRate(),
143
178
  repo_failover_count: this.repoFailoverCount
144
179
  };
@@ -151,7 +186,9 @@ export class RuntimeMetrics {
151
186
  count,
152
187
  totalMs,
153
188
  avgMs: count > 0 ? totalMs / count : 0,
154
- lastMs: timing?.lastMs ?? 0
189
+ lastMs: timing?.lastMs ?? 0,
190
+ p95Ms: percentile(timing?.samples ?? [], 95),
191
+ p99Ms: percentile(timing?.samples ?? [], 99)
155
192
  };
156
193
  }
157
194
  resolveCacheHitRate() {
@@ -488,7 +488,6 @@ export declare class SourceService {
488
488
  private searchTextIntent;
489
489
  private searchPathIntent;
490
490
  private findSymbolHits;
491
- private loadScopedFilePaths;
492
491
  private indexedCandidateLimit;
493
492
  private indexedCandidateLimitForMatch;
494
493
  private extractClassMetadata;
@@ -1208,6 +1208,7 @@ export class SourceService {
1208
1208
  const limit = clampLimit(input.limit, 20, searchLimitCap);
1209
1209
  const regexPattern = match === "regex" ? compileRegex(query) : undefined;
1210
1210
  const queryMode = input.queryMode ?? "auto";
1211
+ this.metrics.recordSearchQueryMode(queryMode);
1211
1212
  const cursorContext = buildSearchCursorContext({
1212
1213
  artifactId: artifact.artifactId,
1213
1214
  query,
@@ -1227,7 +1228,6 @@ export class SourceService {
1227
1228
  const recordHit = (hit) => {
1228
1229
  accumulator.add(hit);
1229
1230
  };
1230
- const hasSeparators = /[._$]/.test(query);
1231
1231
  const tokenOnlyTextIntent = intent === "text" && queryMode === "token";
1232
1232
  if (intent === "symbol") {
1233
1233
  this.searchSymbolIntent(artifact.artifactId, query, match, scope, regexPattern, recordHit);
@@ -1256,10 +1256,6 @@ export class SourceService {
1256
1256
  }
1257
1257
  else {
1258
1258
  this.searchTextIntentIndexed(artifact.artifactId, query, match, scope, recordHit);
1259
- // F-03: queryMode=auto fallback — when indexed returns 0 hits and query has separators, retry with literal scan
1260
- if (queryMode === "auto" && hasSeparators && accumulator.currentCount() === 0) {
1261
- this.searchTextIntent(artifact.artifactId, query, match, scope, regexPattern, recordHit);
1262
- }
1263
1259
  }
1264
1260
  this.metrics.recordSearchIndexedHit();
1265
1261
  }
@@ -3617,6 +3613,7 @@ export class SourceService {
3617
3613
  const candidateLimit = this.indexedCandidateLimitForMatch(match);
3618
3614
  const indexed = this.filesRepo.searchFileCandidates(artifactId, {
3619
3615
  query,
3616
+ match,
3620
3617
  limit: candidateLimit,
3621
3618
  mode: "text"
3622
3619
  });
@@ -3701,13 +3698,20 @@ export class SourceService {
3701
3698
  }
3702
3699
  }
3703
3700
  searchTextIntent(artifactId, query, match, scope, regexPattern, onHit) {
3704
- const filePaths = this.loadScopedFilePaths(artifactId, scope);
3705
3701
  const pageSize = Math.max(1, this.config.searchScanPageSize ?? 250);
3706
- for (const chunk of chunkArray(filePaths, pageSize)) {
3707
- const rows = this.filesRepo.getFileContentsByPaths(artifactId, chunk);
3702
+ const glob = scope?.fileGlob ? buildGlobRegex(normalizePathStyle(scope.fileGlob)) : undefined;
3703
+ let cursor = undefined;
3704
+ while (true) {
3705
+ const page = this.filesRepo.listFileRows(artifactId, { limit: pageSize, cursor });
3708
3706
  this.metrics.recordSearchDbRoundtrip();
3709
- this.metrics.recordSearchRowsScanned(rows.length);
3710
- for (const row of rows) {
3707
+ this.metrics.recordSearchRowsScanned(page.items.length);
3708
+ for (const row of page.items) {
3709
+ if (!checkPackagePrefix(row.filePath, scope?.packagePrefix)) {
3710
+ continue;
3711
+ }
3712
+ if (glob && !glob.test(row.filePath)) {
3713
+ continue;
3714
+ }
3711
3715
  const contentIndex = match === "regex"
3712
3716
  ? matchRegexIndex(row.content, regexPattern)
3713
3717
  : findContentMatchIndex(row.content, query, match);
@@ -3721,29 +3725,44 @@ export class SourceService {
3721
3725
  reasonCodes: ["content_match", `text_${match}`]
3722
3726
  });
3723
3727
  }
3728
+ if (!page.nextCursor) {
3729
+ break;
3730
+ }
3731
+ cursor = page.nextCursor;
3724
3732
  }
3725
3733
  }
3726
3734
  searchPathIntent(artifactId, query, match, scope, regexPattern, onHit) {
3727
- const filePaths = this.loadScopedFilePaths(artifactId, scope);
3728
- const matching = filePaths.flatMap((filePath) => {
3729
- const pathIndex = match === "regex"
3730
- ? matchRegexIndex(filePath, regexPattern)
3731
- : findMatchIndex(filePath, query, match);
3732
- if (pathIndex < 0) {
3733
- return [];
3734
- }
3735
- return [{ filePath, pathIndex }];
3736
- });
3737
3735
  const pageSize = Math.max(1, this.config.searchScanPageSize ?? 250);
3738
- for (const chunk of chunkArray(matching, pageSize)) {
3739
- for (const candidate of chunk) {
3736
+ const glob = scope?.fileGlob ? buildGlobRegex(normalizePathStyle(scope.fileGlob)) : undefined;
3737
+ let cursor = undefined;
3738
+ while (true) {
3739
+ const page = this.filesRepo.listFiles(artifactId, { limit: pageSize, cursor });
3740
+ this.metrics.recordSearchDbRoundtrip();
3741
+ this.metrics.recordSearchRowsScanned(page.items.length);
3742
+ for (const filePath of page.items) {
3743
+ if (!checkPackagePrefix(filePath, scope?.packagePrefix)) {
3744
+ continue;
3745
+ }
3746
+ if (glob && !glob.test(filePath)) {
3747
+ continue;
3748
+ }
3749
+ const pathIndex = match === "regex"
3750
+ ? matchRegexIndex(filePath, regexPattern)
3751
+ : findMatchIndex(filePath, query, match);
3752
+ if (pathIndex < 0) {
3753
+ continue;
3754
+ }
3740
3755
  onHit({
3741
- filePath: candidate.filePath,
3742
- score: scorePathMatch(match, candidate.pathIndex),
3756
+ filePath,
3757
+ score: scorePathMatch(match, pathIndex),
3743
3758
  matchedIn: "path",
3744
3759
  reasonCodes: ["path_match", `path_${match}`]
3745
3760
  });
3746
3761
  }
3762
+ if (!page.nextCursor) {
3763
+ break;
3764
+ }
3765
+ cursor = page.nextCursor;
3747
3766
  }
3748
3767
  }
3749
3768
  findSymbolHits(artifactId, query, match, scope, regexPattern) {
@@ -3806,31 +3825,6 @@ export class SourceService {
3806
3825
  }
3807
3826
  return result;
3808
3827
  }
3809
- loadScopedFilePaths(artifactId, scope) {
3810
- const glob = scope?.fileGlob ? buildGlobRegex(normalizePathStyle(scope.fileGlob)) : undefined;
3811
- const result = [];
3812
- let cursor = undefined;
3813
- const pageSize = Math.max(1, this.config.searchScanPageSize ?? 250);
3814
- while (true) {
3815
- const page = this.filesRepo.listFiles(artifactId, { limit: pageSize, cursor });
3816
- this.metrics.recordSearchDbRoundtrip();
3817
- this.metrics.recordSearchRowsScanned(page.items.length);
3818
- for (const filePath of page.items) {
3819
- if (!checkPackagePrefix(filePath, scope?.packagePrefix)) {
3820
- continue;
3821
- }
3822
- if (glob && !glob.test(filePath)) {
3823
- continue;
3824
- }
3825
- result.push(filePath);
3826
- }
3827
- if (!page.nextCursor) {
3828
- break;
3829
- }
3830
- cursor = page.nextCursor;
3831
- }
3832
- return result;
3833
- }
3834
3828
  indexedCandidateLimit() {
3835
3829
  return Math.min(Math.max(this.config.maxSearchHits * 5, 500), 5000);
3836
3830
  }
@@ -4543,11 +4537,7 @@ export class SourceService {
4543
4537
  publishCacheMetrics() {
4544
4538
  this.metrics.setCacheEntries(this.cacheMetricsState.entries);
4545
4539
  this.metrics.setCacheTotalContentBytes(this.cacheMetricsState.totalContentBytes);
4546
- this.metrics.setCacheArtifactByteAccounting(this.cacheMetricsState.lru.map((row) => ({
4547
- artifact_id: row.artifactId,
4548
- content_bytes: row.totalContentBytes,
4549
- updated_at: row.updatedAt
4550
- })));
4540
+ this.metrics.setCacheArtifactByteAccountingRef(this.cacheMetricsState.lru);
4551
4541
  }
4552
4542
  }
4553
4543
  //# sourceMappingURL=source-service.js.map
@@ -15,6 +15,7 @@ export interface ListFilesOptions {
15
15
  export interface SearchFilesOptions {
16
16
  limit: number;
17
17
  query: string;
18
+ match?: "exact" | "prefix" | "contains" | "regex";
18
19
  cursor?: string;
19
20
  mode?: "mixed" | "text" | "path";
20
21
  fetchLimitOverride?: number;
@@ -102,6 +102,25 @@ function buildPreview(content, query) {
102
102
  const suffix = end < content.length ? "..." : "";
103
103
  return `${prefix}${content.slice(start, end)}${suffix}`.replace(/\s+/g, " ").trim();
104
104
  }
105
+ function tokenizeIndexedQuery(query) {
106
+ return query.match(/[\p{L}\p{N}]+/gu) ?? [];
107
+ }
108
+ function buildIndexedMatchQuery(query, match) {
109
+ const tokens = tokenizeIndexedQuery(query.trim());
110
+ if (tokens.length === 0) {
111
+ return query.trim();
112
+ }
113
+ // Separator-heavy queries become an order-agnostic FTS5 MATCH expression.
114
+ // Whitespace is implicit AND, which keeps "dispatcher.register" on the indexed
115
+ // path while SourceService re-checks hydrated path/content matches before
116
+ // returning hits. Callers can still use literal mode for exact substring scans.
117
+ return tokens.map((token, index) => {
118
+ if (match === "prefix" && index === tokens.length - 1) {
119
+ return `${token}*`;
120
+ }
121
+ return token;
122
+ }).join(" ");
123
+ }
105
124
  export class FilesRepo {
106
125
  db;
107
126
  deleteStmt;
@@ -257,6 +276,7 @@ export class FilesRepo {
257
276
  }
258
277
  const cursor = parseSearchCursor(options.cursor);
259
278
  const likeQuery = `%${normalized}%`;
279
+ const ftsQuery = buildIndexedMatchQuery(normalized, options.match);
260
280
  const mode = options.mode ?? "mixed";
261
281
  // Cursor-adaptive fetch limit: when no cursor, use a generous limit;
262
282
  // with cursor + SQL pushdown, we need far fewer rows.
@@ -294,9 +314,9 @@ export class FilesRepo {
294
314
  }));
295
315
  const mergedByPath = new Map(merged.map((hit) => [hit.filePath, hit]));
296
316
  let contentRows = [];
297
- if (includeContent) {
317
+ if (includeContent && ftsQuery) {
298
318
  try {
299
- contentRows = this.searchFtsStmt.all(artifactId, normalized, fetchLimit);
319
+ contentRows = this.searchFtsStmt.all(artifactId, ftsQuery, fetchLimit);
300
320
  }
301
321
  catch (error) {
302
322
  const message = error instanceof Error ? error.message : String(error);
@@ -305,7 +325,7 @@ export class FilesRepo {
305
325
  }
306
326
  log("warn", "storage.files.fts_syntax_error", {
307
327
  artifactId,
308
- query: normalized,
328
+ query: ftsQuery,
309
329
  message
310
330
  });
311
331
  }
@@ -379,14 +399,18 @@ export class FilesRepo {
379
399
  if (!normalized) {
380
400
  return 0;
381
401
  }
402
+ const ftsQuery = buildIndexedMatchQuery(normalized, "contains");
403
+ if (!ftsQuery) {
404
+ return 0;
405
+ }
382
406
  try {
383
- const row = this.db.prepare(`SELECT COUNT(*) AS cnt FROM files_fts WHERE artifact_id = ? AND files_fts MATCH ?`).get(artifactId, normalized);
407
+ const row = this.db.prepare(`SELECT COUNT(*) AS cnt FROM files_fts WHERE artifact_id = ? AND files_fts MATCH ?`).get(artifactId, ftsQuery);
384
408
  return row?.cnt ?? 0;
385
409
  }
386
410
  catch {
387
411
  log("warn", "storage.files.count_text_candidates_failed", {
388
412
  artifactId,
389
- query: normalized
413
+ query: ftsQuery
390
414
  });
391
415
  return 0;
392
416
  }
@@ -0,0 +1,4 @@
1
+ export declare const TOOL_SURFACE_SECTION_IDS: readonly ["v3-entry-tools", "source-exploration", "version-comparison-symbol-tracking", "mapping-symbols", "nbt-utilities", "mod-analysis", "validation", "registry-diagnostics"];
2
+ export type ToolSurfaceSectionId = (typeof TOOL_SURFACE_SECTION_IDS)[number];
3
+ export type ToolSurfaceLocale = "en" | "ja";
4
+ export declare function renderToolSurfaceSection(locale: ToolSurfaceLocale, sectionId: ToolSurfaceSectionId): string;
@@ -0,0 +1,139 @@
1
+ export const TOOL_SURFACE_SECTION_IDS = [
2
+ "v3-entry-tools",
3
+ "source-exploration",
4
+ "version-comparison-symbol-tracking",
5
+ "mapping-symbols",
6
+ "nbt-utilities",
7
+ "mod-analysis",
8
+ "validation",
9
+ "registry-diagnostics"
10
+ ];
11
+ const SECTION_ROWS = {
12
+ "v3-entry-tools": {
13
+ en: [
14
+ "| `inspect-minecraft` | Start from a version, artifact, class, file, search query, or workspace and route to the most relevant Minecraft inspection flow | `task?`, `subject?`, `detail?`, `include?`, `limit?`, `cursor?`, `includeSnapshots?` | `result.summary`, `versions?`, `subject`, `artifact?`, `class?`, `source?`, `members?`, `search?`, `file?`, `files?` |",
15
+ "| `analyze-symbol` | One entry point for symbol existence checks, namespace mapping, lifecycle tracing, workspace symbol analysis, and API overview | `task`, `subject`, `version?`, `sourceMapping?`, `targetMapping?`, `projectPath?`, `classNameMapping?`, `signatureMode?`, `nameMode?`, `includeKinds?`, `maxRows?`, `maxCandidates?`, `detail?`, `include?` | `result.summary`, `match?`, `candidates?`, `ambiguity?`, `matrix?`, `workspace?` |",
16
+ "| `compare-minecraft` | Compare version pairs, class signatures, registries, or produce a migration-oriented overview | `task?`, `subject`, `detail?`, `include?`, `subject.kind=\"class\".sourcePriority?`, `maxClassResults?`, `maxEntriesPerRegistry?`, `includeFullDiff?`, `limit?` | `result.summary`, `comparison`, `classes?`, `classDiff?`, `registry?`, `migration?` |",
17
+ "| `analyze-mod` | Metadata-first entry point for mod summary, decompile/search flows, class source, and safe remap previews/applies | `task`, `subject`, `query?`, `searchType?`, `targetMapping?`, `outputJar?`, `executionMode?`, `includeFiles?`, `maxFiles?`, `maxLines?`, `maxChars?`, `limit?`, `detail?`, `include?` | `result.summary`, `metadata?`, `decompile?`, `hits?`, `source?`, `operation?` |",
18
+ "| `validate-project` | Project-level validation entry for workspace summaries plus direct Mixin and Access Widener validation | `task`, `subject`, `version?`, `mapping?`, `sourcePriority?`, `scope?`, `preferProjectVersion?`, `preferProjectMapping?`, `sourceRoots?`, `configPaths?`, `minSeverity?`, `hideUncertain?`, `explain?`, `warningMode?`, `warningCategoryFilter?`, `treatInfoAsWarning?`, `includeIssues?`, `detail?`, `include?` | `result.summary`, `project`, `workspace?`, `issues?` |",
19
+ "| `manage-cache` | User-facing cache summary, listing, verification, previewed deletion/pruning/rebuild, and explicit apply operations | `action`, `cacheKinds?`, `selector?`, `executionMode?`, `detail?`, `include?`, `limit?`, `cursor?` | `result.summary`, `stats?`, `cacheEntries?`, `operation?`, `meta.pagination.nextCursor?` |"
20
+ ],
21
+ ja: [
22
+ "| `inspect-minecraft` | バージョン、アーティファクト、クラス、ファイル、検索クエリ、ワークスペースから開始し、最適な Minecraft 調査フローへ振り分ける | `task?`, `subject?`, `detail?`, `include?`, `limit?`, `cursor?`, `includeSnapshots?` | `result.summary`, `versions?`, `subject`, `artifact?`, `class?`, `source?`, `members?`, `search?`, `file?`, `files?` |",
23
+ "| `analyze-symbol` | シンボル存在確認、名前空間マッピング、ライフサイクル追跡、ワークスペースシンボル解析、API 概要の単一エントリーポイント | `task`, `subject`, `version?`, `sourceMapping?`, `targetMapping?`, `projectPath?`, `classNameMapping?`, `signatureMode?`, `nameMode?`, `includeKinds?`, `maxRows?`, `maxCandidates?`, `detail?`, `include?` | `result.summary`, `match?`, `candidates?`, `ambiguity?`, `matrix?`, `workspace?` |",
24
+ "| `compare-minecraft` | バージョンペア比較、クラスシグネチャ比較、レジストリ比較、移行向け概要を提供 | `task?`, `subject`, `detail?`, `include?`, `subject.kind=\"class\".sourcePriority?`, `maxClassResults?`, `maxEntriesPerRegistry?`, `includeFullDiff?`, `limit?` | `result.summary`, `comparison`, `classes?`, `classDiff?`, `registry?`, `migration?` |",
25
+ "| `analyze-mod` | Mod 要約、デコンパイル / 検索フロー、クラスソース、安全なリマップ preview/apply のためのメタデータ優先エントリーポイント | `task`, `subject`, `query?`, `searchType?`, `targetMapping?`, `outputJar?`, `executionMode?`, `includeFiles?`, `maxFiles?`, `maxLines?`, `maxChars?`, `limit?`, `detail?`, `include?` | `result.summary`, `metadata?`, `decompile?`, `hits?`, `source?`, `operation?` |",
26
+ "| `validate-project` | ワークスペース要約と、Mixin / Access Widener の直接検証をまとめたプロジェクト単位の検証エントリー | `task`, `subject`, `version?`, `mapping?`, `sourcePriority?`, `scope?`, `preferProjectVersion?`, `preferProjectMapping?`, `sourceRoots?`, `configPaths?`, `minSeverity?`, `hideUncertain?`, `explain?`, `warningMode?`, `warningCategoryFilter?`, `treatInfoAsWarning?`, `includeIssues?`, `detail?`, `include?` | `result.summary`, `project`, `workspace?`, `issues?` |",
27
+ "| `manage-cache` | ユーザー向けのキャッシュ要約、一覧、検証、preview 付き削除 / prune / rebuild、明示的な apply 操作 | `action`, `cacheKinds?`, `selector?`, `executionMode?`, `detail?`, `include?`, `limit?`, `cursor?` | `result.summary`, `stats?`, `cacheEntries?`, `operation?`, `meta.pagination.nextCursor?` |"
28
+ ]
29
+ },
30
+ "source-exploration": {
31
+ en: [
32
+ "| `list-versions` | List available Minecraft versions from Mojang manifest + local cache | `includeSnapshots?`, `limit?` | `result.latest`, `result.releases[]`, `meta.warnings[]` |",
33
+ "| `resolve-artifact` | Resolve source artifact from `version` / `jar` / `coordinate` | `target`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?` | `artifactId`, `origin`, `mappingApplied`, `qualityFlags[]`, `artifactContents`, `adjacentSourceCandidates?`, `sampleEntries?`, `warnings[]` |",
34
+ "| `find-class` | Resolve simple or fully-qualified class names inside an artifact | `className`, `artifactId`, `limit?` | `matches[]`, `total`, `warnings[]` |",
35
+ "| `get-class-source` | Get class source by artifact target or resolve target on demand (`mode=metadata` by default) | `className`, `target`, `mode?`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?`, `startLine?`, `endLine?`, `maxLines?`, `maxChars?`, `outputFile?` | `mode`, `sourceText`, `returnedRange`, `truncated`, `charsTruncated?`, `outputFile?`, `artifactId`, `returnedNamespace`, `artifactContents`, mapping/provenance metadata |",
36
+ "| `get-class-members` | Get class fields/methods/constructors from bytecode | `className`, `target`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `access?`, `includeSynthetic?`, `includeInherited?`, `memberPattern?`, `maxMembers?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?` | `members.{constructors,fields,methods}`, `counts`, `truncated`, `context`, `returnedNamespace`, `artifactContents`, `warnings[]` |",
37
+ "| `search-class-source` | Search indexed class source for symbols/text/path | `artifactId`, `query`, `intent?`, `match?`, `packagePrefix?`, `fileGlob?`, `symbolKind?`, `queryMode?`, `limit?`, `cursor?` | `hits[]`, `nextCursor?`, `mappingApplied`, `returnedNamespace`, `artifactContents` |",
38
+ "| `get-artifact-file` | Read full source file with byte guard | `artifactId`, `filePath`, `maxBytes?` | `content`, `contentBytes`, `truncated`, `mappingApplied`, `returnedNamespace`, `artifactContents` |",
39
+ "| `list-artifact-files` | List indexed source file paths with cursor pagination | `artifactId`, `prefix?`, `limit?`, `cursor?` | `items[]`, `nextCursor?`, `mappingApplied`, `artifactContents`, `warnings[]` |",
40
+ "| `index-artifact` | Rebuild index metadata for an existing artifact | `artifactId`, `force?` | `reindexed`, `reason`, `counts`, `indexedAt`, `durationMs` |"
41
+ ],
42
+ ja: [
43
+ "| `list-versions` | Mojang マニフェストとローカルキャッシュから利用可能な Minecraft バージョンを一覧表示 | `includeSnapshots?`, `limit?` | `result.latest`, `result.releases[]`, `meta.warnings[]` |",
44
+ "| `resolve-artifact` | `version` / `jar` / `coordinate` からソースアーティファクトを解決 | `target`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?` | `artifactId`, `origin`, `mappingApplied`, `qualityFlags[]`, `artifactContents`, `adjacentSourceCandidates?`, `sampleEntries?`, `warnings[]` |",
45
+ "| `find-class` | アーティファクト内で簡易名または完全修飾クラス名を解決 | `className`, `artifactId`, `limit?` | `matches[]`, `total`, `warnings[]` |",
46
+ "| `get-class-source` | アーティファクトターゲットからクラスソースを取得し、必要に応じてその場で解決する(デフォルトは `mode=metadata`) | `className`, `target`, `mode?`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?`, `startLine?`, `endLine?`, `maxLines?`, `maxChars?`, `outputFile?` | `mode`, `sourceText`, `returnedRange`, `truncated`, `charsTruncated?`, `outputFile?`, `artifactId`, `returnedNamespace`, `artifactContents`, マッピング / 来歴メタデータ |",
47
+ "| `get-class-members` | バイトコードからクラスのフィールド / メソッド / コンストラクタを取得 | `className`, `target`, `mapping?`, `sourcePriority?`, `allowDecompile?`, `access?`, `includeSynthetic?`, `includeInherited?`, `memberPattern?`, `maxMembers?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `strictVersion?` | `members.{constructors,fields,methods}`, `counts`, `truncated`, `context`, `returnedNamespace`, `artifactContents`, `warnings[]` |",
48
+ "| `search-class-source` | インデックス化されたクラスソースをシンボル / テキスト / パスで検索 | `artifactId`, `query`, `intent?`, `match?`, `packagePrefix?`, `fileGlob?`, `symbolKind?`, `queryMode?`, `limit?`, `cursor?` | `hits[]`, `nextCursor?`, `mappingApplied`, `returnedNamespace`, `artifactContents` |",
49
+ "| `get-artifact-file` | バイト上限付きでソースファイル全体を読み取る | `artifactId`, `filePath`, `maxBytes?` | `content`, `contentBytes`, `truncated`, `mappingApplied`, `returnedNamespace`, `artifactContents` |",
50
+ "| `list-artifact-files` | インデックス化されたソースファイルパスをカーソルページネーション付きで一覧表示 | `artifactId`, `prefix?`, `limit?`, `cursor?` | `items[]`, `nextCursor?`, `mappingApplied`, `artifactContents`, `warnings[]` |",
51
+ "| `index-artifact` | 既存アーティファクトのインデックスメタデータを再構築 | `artifactId`, `force?` | `reindexed`, `reason`, `counts`, `indexedAt`, `durationMs` |"
52
+ ]
53
+ },
54
+ "version-comparison-symbol-tracking": {
55
+ en: [
56
+ "| `trace-symbol-lifecycle` | Trace when `Class.method` exists across Minecraft versions (`descriptor` omitted = name-only lookup) | `symbol`, `descriptor?`, `fromVersion?`, `toVersion?`, `mapping?`, `sourcePriority?`, `includeSnapshots?`, `maxVersions?`, `includeTimeline?` | `presence.firstSeen`, `presence.lastSeen`, `presence.missingBetween[]`, `presence.existsNow`, `timeline?`, `warnings[]` |",
57
+ "| `diff-class-signatures` | Compare one class between two versions and return member deltas | `className`, `fromVersion`, `toVersion`, `mapping?`, `sourcePriority?`, `includeFullDiff?` | `classChange`, `constructors/methods/fields.{added,removed,modified}`, `modified`, `modified[].{key,changed,from?,to?}`, `summary`, `warnings[]` |",
58
+ "| `compare-versions` | Compare class/registry changes between two versions | `fromVersion`, `toVersion`, `category?`, `packageFilter?`, `maxClassResults?` | `classes`, `registry`, `summary`, `warnings[]` |"
59
+ ],
60
+ ja: [
61
+ "| `trace-symbol-lifecycle` | `Class.method` が Minecraft のどのバージョンで存在するかを追跡(`descriptor` 省略時は name-only lookup) | `symbol`, `descriptor?`, `fromVersion?`, `toVersion?`, `mapping?`, `sourcePriority?`, `includeSnapshots?`, `maxVersions?`, `includeTimeline?` | `presence.firstSeen`, `presence.lastSeen`, `presence.missingBetween[]`, `presence.existsNow`, `timeline?`, `warnings[]` |",
62
+ "| `diff-class-signatures` | 2 つのバージョン間で 1 つのクラスを比較し、メンバー差分を返す | `className`, `fromVersion`, `toVersion`, `mapping?`, `sourcePriority?`, `includeFullDiff?` | `classChange`, `constructors/methods/fields.{added,removed,modified}`, `modified`, `modified[].{key,changed,from?,to?}`, `summary`, `warnings[]` |",
63
+ "| `compare-versions` | 2 つのバージョン間でクラス / レジストリ変更を比較 | `fromVersion`, `toVersion`, `category?`, `packageFilter?`, `maxClassResults?` | `classes`, `registry`, `summary`, `warnings[]` |"
64
+ ]
65
+ },
66
+ "mapping-symbols": {
67
+ en: [
68
+ "| `find-mapping` | Find mapping candidates for class/field/method symbols between namespaces | `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `targetMapping`, `sourcePriority?`, `disambiguation?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `ambiguityReasons?`, `provenance?`, `meta.warnings[]` |",
69
+ "| `resolve-method-mapping-exact` | Resolve one method mapping with strict owner+name+descriptor matching | `version`, `name`, `owner`, `descriptor`, `sourceMapping`, `targetMapping`, `sourcePriority?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `provenance?`, `meta.warnings[]` |",
70
+ "| `get-class-api-matrix` | Show one class API as a mapping matrix (`obfuscated/mojang/intermediary/yarn`) | `version`, `className`, `classNameMapping`, `includeKinds?`, `sourcePriority?`, `maxRows?` | `classIdentity`, `rows[]`, `rowCount`, `rowsTruncated?`, `ambiguousRowCount?`, `meta.warnings[]` |",
71
+ "| `resolve-workspace-symbol` | Resolve compile-visible symbol names for a Gradle workspace (`build.gradle/.kts`) | `projectPath`, `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `sourcePriority?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `workspaceDetection`, `meta.warnings[]` |",
72
+ "| `check-symbol-exists` | Strict symbol presence check for class/field/method | `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `sourcePriority?`, `nameMode?`, `signatureMode?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `meta.warnings[]` |"
73
+ ],
74
+ ja: [
75
+ "| `find-mapping` | クラス / フィールド / メソッドのシンボルについて、名前空間間のマッピング候補を検索 | `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `targetMapping`, `sourcePriority?`, `disambiguation?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `ambiguityReasons?`, `provenance?`, `meta.warnings[]` |",
76
+ "| `resolve-method-mapping-exact` | owner + name + descriptor の厳密一致で 1 つのメソッドマッピングを解決 | `version`, `name`, `owner`, `descriptor`, `sourceMapping`, `targetMapping`, `sourcePriority?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `provenance?`, `meta.warnings[]` |",
77
+ "| `get-class-api-matrix` | 1 つのクラス API をマッピングマトリクス(`obfuscated/mojang/intermediary/yarn`)として表示 | `version`, `className`, `classNameMapping`, `includeKinds?`, `sourcePriority?`, `maxRows?` | `classIdentity`, `rows[]`, `rowCount`, `rowsTruncated?`, `ambiguousRowCount?`, `meta.warnings[]` |",
78
+ "| `resolve-workspace-symbol` | Gradle ワークスペース(`build.gradle/.kts`)でコンパイル時に見えるシンボル名を解決 | `projectPath`, `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `sourcePriority?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `workspaceDetection`, `meta.warnings[]` |",
79
+ "| `check-symbol-exists` | クラス / フィールド / メソッドの厳密な存在確認 | `version`, `kind`, `name`, `owner?`, `descriptor?`, `sourceMapping`, `sourcePriority?`, `nameMode?`, `signatureMode?`, `maxCandidates?` | `querySymbol`, `mappingContext`, `resolved`, `status`, `resolvedSymbol?`, `candidates[]`, `candidateCount`, `candidatesTruncated?`, `meta.warnings[]` |"
80
+ ]
81
+ },
82
+ "nbt-utilities": {
83
+ en: [
84
+ "| `nbt-to-json` | Decode Java Edition NBT binary (`base64`) to typed JSON | `nbtBase64`, `compression?` (`none`, `gzip`, `auto`) | `typedJson`, `meta.compressionDetected`, `meta.inputBytes` |",
85
+ "| `nbt-apply-json-patch` | Apply RFC 6902 patch (`add/remove/replace/test`) to typed NBT JSON | `typedJson`, `patch` | `typedJson`, `meta.appliedOps`, `meta.testOps`, `meta.changed` |",
86
+ "| `json-to-nbt` | Encode typed JSON back to Java Edition NBT binary (`base64`) | `typedJson`, `compression?` (`none`, `gzip`) | `nbtBase64`, `meta.outputBytes`, `meta.compressionApplied` |"
87
+ ],
88
+ ja: [
89
+ "| `nbt-to-json` | Java Edition の NBT バイナリ(`base64`)を型付き JSON にデコード | `nbtBase64`, `compression?` (`none`, `gzip`, `auto`) | `typedJson`, `meta.compressionDetected`, `meta.inputBytes` |",
90
+ "| `nbt-apply-json-patch` | RFC 6902 パッチ(`add/remove/replace/test`)を型付き NBT JSON に適用 | `typedJson`, `patch` | `typedJson`, `meta.appliedOps`, `meta.testOps`, `meta.changed` |",
91
+ "| `json-to-nbt` | 型付き JSON を Java Edition の NBT バイナリ(`base64`)へ再エンコード | `typedJson`, `compression?` (`none`, `gzip`) | `nbtBase64`, `meta.outputBytes`, `meta.compressionApplied` |"
92
+ ]
93
+ },
94
+ "mod-analysis": {
95
+ en: [
96
+ "| `analyze-mod-jar` | Extract mod metadata/dependencies/entrypoints from mod JAR | `jarPath`, `includeClasses?` | `modId`, `loader`, `jarKind`, `dependencies`, `entrypoints`, `mixinConfigs`, class stats |",
97
+ "| `decompile-mod-jar` | Decompile mod JAR and optionally return one class source | `jarPath`, `className?`, `includeFiles?`, `maxFiles?` | `outputDir`, `fileCount`, `files?`, `returnedFileCount?`, `filesTruncated?`, `filesOmitted?`, `source?`, `warnings[]` |",
98
+ "| `get-mod-class-source` | Read one class source from decompiled mod cache | `jarPath`, `className`, `maxLines?`, `maxChars?`, `outputFile?` | `className`, `content`, `totalLines`, `truncated?`, `charsTruncated?`, `outputFilePath?`, `warnings[]` |",
99
+ "| `search-mod-source` | Search decompiled mod source by class/method/field/content | `jarPath`, `query`, `searchType?`, `limit?` | `hits[]`, `totalHits`, `truncated`, `warnings[]` |",
100
+ "| `remap-mod-jar` | Remap a Fabric/Quilt mod JAR to yarn/mojang names; Mojang-mapped inputs are copied for `targetMapping=\"mojang\"` | `inputJar`, `targetMapping`, `mcVersion?`, `outputJar?` | `outputJar`, `mcVersion`, `fromMapping`, `targetMapping`, `resolvedTargetNamespace`, `warnings[]` |"
101
+ ],
102
+ ja: [
103
+ "| `analyze-mod-jar` | Mod JAR から Mod メタデータ / 依存関係 / エントリポイントを抽出 | `jarPath`, `includeClasses?` | `modId`, `loader`, `jarKind`, `dependencies`, `entrypoints`, `mixinConfigs`, class stats |",
104
+ "| `decompile-mod-jar` | Mod JAR をデコンパイルし、必要に応じて 1 つのクラスソースを返す | `jarPath`, `className?`, `includeFiles?`, `maxFiles?` | `outputDir`, `fileCount`, `files?`, `returnedFileCount?`, `filesTruncated?`, `filesOmitted?`, `source?`, `warnings[]` |",
105
+ "| `get-mod-class-source` | デコンパイル済み Mod キャッシュから 1 つのクラスソースを読み取る | `jarPath`, `className`, `maxLines?`, `maxChars?`, `outputFile?` | `className`, `content`, `totalLines`, `truncated?`, `charsTruncated?`, `outputFilePath?`, `warnings[]` |",
106
+ "| `search-mod-source` | デコンパイル済み Mod ソースを class / method / field / content で検索 | `jarPath`, `query`, `searchType?`, `limit?` | `hits[]`, `totalHits`, `truncated`, `warnings[]` |",
107
+ "| `remap-mod-jar` | Fabric / Quilt Mod JAR を yarn / mojang 名へリマップする。`targetMapping=\"mojang\"` で Mojang マップ済み入力はコピー扱い | `inputJar`, `targetMapping`, `mcVersion?`, `outputJar?` | `outputJar`, `mcVersion`, `fromMapping`, `targetMapping`, `resolvedTargetNamespace`, `warnings[]` |"
108
+ ]
109
+ },
110
+ "validation": {
111
+ en: [
112
+ "| `validate-mixin` | Parse/validate Mixin source against target Minecraft version | `input`, `sourceRoots?`, `version`, `mapping?`, `sourcePriority?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `minSeverity?`, `hideUncertain?`, `warningMode?`, `preferProjectMapping?`, `reportMode?`, `warningCategoryFilter?`, `treatInfoAsWarning?`, `explain?`, `includeIssues?` | `mode`, `results[].validationStatus`, `summary.partial`, `issueSummary?`, `provenance?`, `incompleteReasons?`, `toolHealth?`, `confidenceScore?`, `confidenceBreakdown?` |",
113
+ "| `validate-access-widener` | Parse/validate Access Widener content against target version | `content`, `version`, `mapping?`, `sourcePriority?` | `valid`, `issues[]`, `warnings[]`, `summary` |"
114
+ ],
115
+ ja: [
116
+ "| `validate-mixin` | 対象 Minecraft バージョンに対して Mixin ソースを解析 / 検証 | `input`, `sourceRoots?`, `version`, `mapping?`, `sourcePriority?`, `projectPath?`, `scope?`, `preferProjectVersion?`, `minSeverity?`, `hideUncertain?`, `warningMode?`, `preferProjectMapping?`, `reportMode?`, `warningCategoryFilter?`, `treatInfoAsWarning?`, `explain?`, `includeIssues?` | `mode`, `results[].validationStatus`, `summary.partial`, `issueSummary?`, `provenance?`, `incompleteReasons?`, `toolHealth?`, `confidenceScore?`, `confidenceBreakdown?` |",
117
+ "| `validate-access-widener` | 対象バージョンに対して Access Widener の内容を解析 / 検証 | `content`, `version`, `mapping?`, `sourcePriority?` | `valid`, `issues[]`, `warnings[]`, `summary` |"
118
+ ]
119
+ },
120
+ "registry-diagnostics": {
121
+ en: [
122
+ "| `get-registry-data` | Get generated registry snapshots (blocks/items/entities etc.) | `version`, `registry?`, `includeData?`, `maxEntriesPerRegistry?` | `registries`, `data?`, `entryCount`, `returnedEntryCount?`, `registryEntryCounts?`, `dataTruncated?`, `warnings[]` |",
123
+ "| `get-runtime-metrics` | Inspect runtime counters and latency snapshots | none | `result.*` runtime metrics, `meta` envelope |"
124
+ ],
125
+ ja: [
126
+ "| `get-registry-data` | 生成済みレジストリスナップショット(ブロック / アイテム / エンティティなど)を取得 | `version`, `registry?`, `includeData?`, `maxEntriesPerRegistry?` | `registries`, `data?`, `entryCount`, `returnedEntryCount?`, `registryEntryCounts?`, `dataTruncated?`, `warnings[]` |",
127
+ "| `get-runtime-metrics` | ランタイムカウンターとレイテンシスナップショットを確認 | none | `result.*` runtime metrics, `meta` envelope |"
128
+ ]
129
+ }
130
+ };
131
+ export function renderToolSurfaceSection(locale, sectionId) {
132
+ const header = locale === "en"
133
+ ? "| Tool | Purpose | Key Inputs | Key Outputs |"
134
+ : "| ツール | 役割 | 主な入力 | 主な出力 |";
135
+ const divider = "| --- | --- | --- | --- |";
136
+ const rows = SECTION_ROWS[sectionId][locale];
137
+ return [header, divider, ...rows].join("\n");
138
+ }
139
+ //# sourceMappingURL=tool-contract-manifest.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhisang/minecraft-modding-mcp",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "MCP server with utilities for Minecraft modding workflows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",