@adhisang/minecraft-modding-mcp 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +86 -46
- package/dist/index.js +150 -174
- package/dist/mapping-pipeline-service.d.ts +1 -1
- package/dist/mapping-pipeline-service.js +5 -5
- package/dist/mapping-service.d.ts +3 -4
- package/dist/mapping-service.js +40 -46
- package/dist/mcp-helpers.d.ts +10 -2
- package/dist/mcp-helpers.js +59 -5
- package/dist/minecraft-explorer-service.d.ts +1 -1
- package/dist/minecraft-explorer-service.js +1 -1
- package/dist/mixin-validator.js +5 -5
- package/dist/mojang-tiny-mapping-service.js +26 -26
- package/dist/resources.js +7 -7
- package/dist/search-hit-accumulator.d.ts +0 -3
- package/dist/search-hit-accumulator.js +4 -4
- package/dist/source-resolver.d.ts +1 -0
- package/dist/source-resolver.js +94 -2
- package/dist/source-service.d.ts +34 -43
- package/dist/source-service.js +597 -670
- package/dist/storage/files-repo.d.ts +9 -0
- package/dist/storage/files-repo.js +42 -0
- package/dist/storage/migrations.d.ts +1 -1
- package/dist/storage/migrations.js +6 -2
- package/dist/storage/schema.d.ts +1 -0
- package/dist/storage/schema.js +7 -0
- package/dist/tool-input.d.ts +6 -0
- package/dist/tool-input.js +64 -0
- package/dist/types.d.ts +1 -1
- package/package.json +4 -1
|
@@ -33,6 +33,12 @@ export interface SearchFileCandidateResult {
|
|
|
33
33
|
export interface SearchFilesWithContentResult extends SearchFilesResult {
|
|
34
34
|
content: string;
|
|
35
35
|
}
|
|
36
|
+
export interface FileContentPrefixRow {
|
|
37
|
+
artifactId: string;
|
|
38
|
+
filePath: string;
|
|
39
|
+
contentPrefix: string;
|
|
40
|
+
truncated: boolean;
|
|
41
|
+
}
|
|
36
42
|
export interface ListFileRowsOptions {
|
|
37
43
|
limit: number;
|
|
38
44
|
cursor?: string;
|
|
@@ -50,6 +56,7 @@ export declare class FilesRepo {
|
|
|
50
56
|
private readonly searchPathStmt;
|
|
51
57
|
private readonly searchFtsStmt;
|
|
52
58
|
private readonly getByPathsStmtCache;
|
|
59
|
+
private readonly getPrefixByPathsStmtCache;
|
|
53
60
|
constructor(db: SqliteDatabase);
|
|
54
61
|
clearFilesForArtifact(artifactId: string): void;
|
|
55
62
|
insertFilesForArtifact(artifactId: string, files: IndexedFile[]): void;
|
|
@@ -59,6 +66,7 @@ export declare class FilesRepo {
|
|
|
59
66
|
listFiles(artifactId: string, options: ListFilesOptions): PagedResult<string>;
|
|
60
67
|
listFileRows(artifactId: string, options: ListFileRowsOptions): PagedResult<FileRow>;
|
|
61
68
|
getFileContentsByPaths(artifactId: string, filePaths: string[]): FileRow[];
|
|
69
|
+
getFileContentPrefixesByPaths(artifactId: string, filePaths: string[], maxChars: number): FileContentPrefixRow[];
|
|
62
70
|
searchFileCandidates(artifactId: string, options: SearchFilesOptions): PagedResult<SearchFileCandidateResult> & {
|
|
63
71
|
scannedRows: number;
|
|
64
72
|
dbRoundtrips: number;
|
|
@@ -74,5 +82,6 @@ export declare class FilesRepo {
|
|
|
74
82
|
totalContentBytes(): number;
|
|
75
83
|
contentBytesForArtifact(artifactId: string): number;
|
|
76
84
|
private getFileContentsByPathsStmt;
|
|
85
|
+
private getFileContentPrefixesByPathsStmt;
|
|
77
86
|
}
|
|
78
87
|
export {};
|
|
@@ -114,6 +114,7 @@ export class FilesRepo {
|
|
|
114
114
|
searchPathStmt;
|
|
115
115
|
searchFtsStmt;
|
|
116
116
|
getByPathsStmtCache = new Map();
|
|
117
|
+
getPrefixByPathsStmtCache = new Map();
|
|
117
118
|
constructor(db) {
|
|
118
119
|
this.db = db;
|
|
119
120
|
this.deleteStmt = this.db.prepare(`
|
|
@@ -249,6 +250,27 @@ export class FilesRepo {
|
|
|
249
250
|
]));
|
|
250
251
|
return uniquePaths.map((path) => byPath.get(path)).filter((row) => row != null);
|
|
251
252
|
}
|
|
253
|
+
getFileContentPrefixesByPaths(artifactId, filePaths, maxChars) {
|
|
254
|
+
if (filePaths.length === 0) {
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
const normalizedMaxChars = Math.max(1, Math.trunc(maxChars));
|
|
258
|
+
const uniquePaths = [...new Set(filePaths)];
|
|
259
|
+
const stmt = this.getFileContentPrefixesByPathsStmt(uniquePaths.length, normalizedMaxChars);
|
|
260
|
+
const rows = stmt.all(normalizedMaxChars, artifactId, ...uniquePaths);
|
|
261
|
+
const byPath = new Map(rows.map((row) => [
|
|
262
|
+
row.file_path,
|
|
263
|
+
{
|
|
264
|
+
artifactId: row.artifact_id,
|
|
265
|
+
filePath: row.file_path,
|
|
266
|
+
contentPrefix: row.content_prefix,
|
|
267
|
+
truncated: row.content_length > row.content_prefix.length
|
|
268
|
+
}
|
|
269
|
+
]));
|
|
270
|
+
return uniquePaths
|
|
271
|
+
.map((path) => byPath.get(path))
|
|
272
|
+
.filter((row) => row != null);
|
|
273
|
+
}
|
|
252
274
|
searchFileCandidates(artifactId, options) {
|
|
253
275
|
const normalized = options.query.trim();
|
|
254
276
|
if (!normalized) {
|
|
@@ -460,5 +482,25 @@ export class FilesRepo {
|
|
|
460
482
|
this.getByPathsStmtCache.set(normalizedCount, stmt);
|
|
461
483
|
return stmt;
|
|
462
484
|
}
|
|
485
|
+
getFileContentPrefixesByPathsStmt(pathCount, maxChars) {
|
|
486
|
+
const normalizedCount = Math.max(1, Math.trunc(pathCount));
|
|
487
|
+
const normalizedMaxChars = Math.max(1, Math.trunc(maxChars));
|
|
488
|
+
const cacheKey = `${normalizedCount}:${normalizedMaxChars}`;
|
|
489
|
+
const cached = this.getPrefixByPathsStmtCache.get(cacheKey);
|
|
490
|
+
if (cached) {
|
|
491
|
+
return cached;
|
|
492
|
+
}
|
|
493
|
+
if (this.getPrefixByPathsStmtCache.size >= 128) {
|
|
494
|
+
this.getPrefixByPathsStmtCache.clear();
|
|
495
|
+
}
|
|
496
|
+
const placeholders = Array.from({ length: normalizedCount }, () => "?").join(", ");
|
|
497
|
+
const stmt = this.db.prepare(`
|
|
498
|
+
SELECT artifact_id, file_path, substr(content, 1, ?) AS content_prefix, length(content) AS content_length
|
|
499
|
+
FROM files
|
|
500
|
+
WHERE artifact_id = ? AND file_path IN (${placeholders})
|
|
501
|
+
`);
|
|
502
|
+
this.getPrefixByPathsStmtCache.set(cacheKey, stmt);
|
|
503
|
+
return stmt;
|
|
504
|
+
}
|
|
463
505
|
}
|
|
464
506
|
//# sourceMappingURL=files-repo.js.map
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { createError, ERROR_CODES } from "../errors.js";
|
|
2
|
-
import { SCHEMA_V1_STATEMENTS } from "./schema.js";
|
|
3
|
-
export const LATEST_SCHEMA_VERSION =
|
|
2
|
+
import { SCHEMA_V1_STATEMENTS, SCHEMA_V2_STATEMENTS } from "./schema.js";
|
|
3
|
+
export const LATEST_SCHEMA_VERSION = 2;
|
|
4
4
|
const migrations = [
|
|
5
5
|
{
|
|
6
6
|
version: 1,
|
|
7
7
|
statements: SCHEMA_V1_STATEMENTS
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
version: 2,
|
|
11
|
+
statements: SCHEMA_V2_STATEMENTS
|
|
8
12
|
}
|
|
9
13
|
];
|
|
10
14
|
function selectSchemaVersion(tx) {
|
package/dist/storage/schema.d.ts
CHANGED
package/dist/storage/schema.js
CHANGED
|
@@ -157,4 +157,11 @@ export const SCHEMA_V1_STATEMENTS = [
|
|
|
157
157
|
);
|
|
158
158
|
END`
|
|
159
159
|
];
|
|
160
|
+
export const SCHEMA_V2_STATEMENTS = [
|
|
161
|
+
`DELETE FROM symbols`,
|
|
162
|
+
`DELETE FROM files`,
|
|
163
|
+
`DELETE FROM artifact_content_bytes`,
|
|
164
|
+
`DELETE FROM artifact_index_meta`,
|
|
165
|
+
`DELETE FROM artifacts`
|
|
166
|
+
];
|
|
160
167
|
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const POSITIVE_INT_FIELD_NAMES = new Set([
|
|
2
|
+
"limit",
|
|
3
|
+
"startLine",
|
|
4
|
+
"endLine",
|
|
5
|
+
"maxLines",
|
|
6
|
+
"maxChars",
|
|
7
|
+
"maxMembers",
|
|
8
|
+
"maxBytes",
|
|
9
|
+
"maxVersions",
|
|
10
|
+
"maxClassResults"
|
|
11
|
+
]);
|
|
12
|
+
const MAPPING_FIELD_NAMES = new Set(["mapping", "sourceMapping", "targetMapping", "classNameMapping"]);
|
|
13
|
+
function coerceTopLevelNumericStrings(value) {
|
|
14
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
const output = {};
|
|
18
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
19
|
+
if (typeof entry === "string" && POSITIVE_INT_FIELD_NAMES.has(key)) {
|
|
20
|
+
const trimmed = entry.trim();
|
|
21
|
+
if (/^\d+$/.test(trimmed)) {
|
|
22
|
+
output[key] = Number.parseInt(trimmed, 10);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
output[key] = entry;
|
|
27
|
+
}
|
|
28
|
+
return output;
|
|
29
|
+
}
|
|
30
|
+
function collectRemovedOfficialNamespacePaths(value) {
|
|
31
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const matches = [];
|
|
35
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
36
|
+
if (typeof entry === "string" && MAPPING_FIELD_NAMES.has(key) && entry.trim() === "official") {
|
|
37
|
+
matches.push(key);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return matches;
|
|
41
|
+
}
|
|
42
|
+
function replaceRemovedOfficialMappings(value) {
|
|
43
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const output = {};
|
|
47
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
48
|
+
output[key] =
|
|
49
|
+
typeof entry === "string" && MAPPING_FIELD_NAMES.has(key) && entry.trim() === "official"
|
|
50
|
+
? "obfuscated"
|
|
51
|
+
: entry;
|
|
52
|
+
}
|
|
53
|
+
return output;
|
|
54
|
+
}
|
|
55
|
+
export function prepareToolInput(rawInput) {
|
|
56
|
+
const normalizedInput = coerceTopLevelNumericStrings(rawInput);
|
|
57
|
+
const removedOfficialPaths = collectRemovedOfficialNamespacePaths(normalizedInput);
|
|
58
|
+
return {
|
|
59
|
+
normalizedInput,
|
|
60
|
+
removedOfficialPaths,
|
|
61
|
+
suggestedReplacementInput: removedOfficialPaths.length > 0 ? replaceRemovedOfficialMappings(normalizedInput) : undefined
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=tool-input.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type SourceOrigin = "local-jar" | "local-m2" | "remote-repo" | "decompiled";
|
|
2
|
-
export type SourceMapping = "
|
|
2
|
+
export type SourceMapping = "obfuscated" | "mojang" | "intermediary" | "yarn";
|
|
3
3
|
export type MappingSourcePriority = "loom-first" | "maven-first";
|
|
4
4
|
export type ArtifactTargetKind = "version" | "jar" | "coordinate";
|
|
5
5
|
export type ArtifactScope = "vanilla" | "merged" | "loader";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhisang/minecraft-modding-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "MCP server with utilities for Minecraft modding workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
],
|
|
40
40
|
"author": "adhi-jp",
|
|
41
41
|
"license": "MIT",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
42
45
|
"repository": "github:adhi-jp/minecraft-modding-mcp",
|
|
43
46
|
"bugs": "https://github.com/adhi-jp/minecraft-modding-mcp/issues",
|
|
44
47
|
"homepage": "https://github.com/adhi-jp/minecraft-modding-mcp#readme",
|