@adhisang/minecraft-modding-mcp 2.0.0 → 3.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 +62 -0
- package/README.md +139 -30
- package/dist/cache-registry.d.ts +95 -0
- package/dist/cache-registry.js +541 -0
- package/dist/cli.js +31 -4
- package/dist/compat-stdio-transport.d.ts +2 -7
- package/dist/compat-stdio-transport.js +12 -154
- package/dist/entry-tools/analyze-mod-service.d.ts +207 -0
- package/dist/entry-tools/analyze-mod-service.js +253 -0
- package/dist/entry-tools/analyze-symbol-service.d.ts +209 -0
- package/dist/entry-tools/analyze-symbol-service.js +304 -0
- package/dist/entry-tools/compare-minecraft-service.d.ts +210 -0
- package/dist/entry-tools/compare-minecraft-service.js +397 -0
- package/dist/entry-tools/entry-tool-schema.d.ts +6 -0
- package/dist/entry-tools/entry-tool-schema.js +10 -0
- package/dist/entry-tools/inspect-minecraft-service.d.ts +1953 -0
- package/dist/entry-tools/inspect-minecraft-service.js +876 -0
- package/dist/entry-tools/manage-cache-service.d.ts +130 -0
- package/dist/entry-tools/manage-cache-service.js +229 -0
- package/dist/entry-tools/request-normalizers.d.ts +10 -0
- package/dist/entry-tools/request-normalizers.js +36 -0
- package/dist/entry-tools/response-contract.d.ts +44 -0
- package/dist/entry-tools/response-contract.js +96 -0
- package/dist/entry-tools/validate-project-service.d.ts +543 -0
- package/dist/entry-tools/validate-project-service.js +381 -0
- package/dist/index.js +495 -42
- package/dist/json-rpc-framing.d.ts +22 -0
- package/dist/json-rpc-framing.js +168 -0
- package/dist/mapping-pipeline-service.js +9 -1
- package/dist/mapping-service.d.ts +9 -0
- package/dist/mapping-service.js +183 -60
- package/dist/minecraft-explorer-service.d.ts +0 -1
- package/dist/minecraft-explorer-service.js +119 -23
- package/dist/mixin-validator.d.ts +24 -2
- package/dist/mixin-validator.js +223 -98
- package/dist/mod-decompile-service.d.ts +5 -0
- package/dist/mod-decompile-service.js +40 -5
- package/dist/mod-remap-service.js +142 -30
- package/dist/path-resolver.js +41 -4
- package/dist/registry-service.d.ts +10 -1
- package/dist/registry-service.js +154 -22
- package/dist/search-hit-accumulator.js +23 -2
- package/dist/source-jar-reader.js +16 -2
- package/dist/source-resolver.js +6 -7
- package/dist/source-service.d.ts +42 -4
- package/dist/source-service.js +781 -127
- package/dist/stdio-supervisor.d.ts +46 -0
- package/dist/stdio-supervisor.js +349 -0
- package/dist/storage/files-repo.d.ts +3 -9
- package/dist/storage/files-repo.js +66 -43
- package/dist/symbols/symbol-extractor.js +6 -4
- package/dist/tool-execution-gate.d.ts +15 -0
- package/dist/tool-execution-gate.js +58 -0
- package/dist/version-diff-service.js +10 -5
- package/dist/version-service.js +7 -2
- package/dist/workspace-mapping-service.js +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export type FramingMode = "unknown" | "line" | "content-length";
|
|
3
|
+
export type ConcreteFramingMode = Exclude<FramingMode, "unknown">;
|
|
4
|
+
export type ParsedJsonRpcFrame = {
|
|
5
|
+
message: JSONRPCMessage;
|
|
6
|
+
mode: ConcreteFramingMode;
|
|
7
|
+
};
|
|
8
|
+
export declare function encodeJsonRpcMessage(message: JSONRPCMessage, mode: ConcreteFramingMode): Buffer;
|
|
9
|
+
export declare class JsonRpcFrameReader {
|
|
10
|
+
private mode;
|
|
11
|
+
private buffer;
|
|
12
|
+
get currentMode(): FramingMode;
|
|
13
|
+
reset(): void;
|
|
14
|
+
clear(): void;
|
|
15
|
+
processChunk(chunk: Buffer, handlers: {
|
|
16
|
+
onFrame: (frame: ParsedJsonRpcFrame) => void;
|
|
17
|
+
onError: (error: Error) => void;
|
|
18
|
+
}): void;
|
|
19
|
+
private detectMode;
|
|
20
|
+
private readLineDelimitedMessage;
|
|
21
|
+
private readContentLengthMessage;
|
|
22
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { JSONRPCMessageSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
function findHeaderBoundary(buffer) {
|
|
3
|
+
const crlfBoundary = buffer.indexOf("\r\n\r\n");
|
|
4
|
+
if (crlfBoundary !== -1) {
|
|
5
|
+
return { index: crlfBoundary, delimiterBytes: 4 };
|
|
6
|
+
}
|
|
7
|
+
const lfBoundary = buffer.indexOf("\n\n");
|
|
8
|
+
if (lfBoundary !== -1) {
|
|
9
|
+
return { index: lfBoundary, delimiterBytes: 2 };
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
function parseJsonRpcMessage(json) {
|
|
14
|
+
return JSONRPCMessageSchema.parse(JSON.parse(json));
|
|
15
|
+
}
|
|
16
|
+
function asError(value) {
|
|
17
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
18
|
+
}
|
|
19
|
+
export function encodeJsonRpcMessage(message, mode) {
|
|
20
|
+
const json = JSON.stringify(message);
|
|
21
|
+
return Buffer.from(mode === "content-length"
|
|
22
|
+
? `Content-Length: ${Buffer.byteLength(json, "utf8")}\r\n\r\n${json}`
|
|
23
|
+
: `${json}\n`, "utf8");
|
|
24
|
+
}
|
|
25
|
+
export class JsonRpcFrameReader {
|
|
26
|
+
mode = "unknown";
|
|
27
|
+
buffer = Buffer.alloc(0);
|
|
28
|
+
get currentMode() {
|
|
29
|
+
return this.mode;
|
|
30
|
+
}
|
|
31
|
+
reset() {
|
|
32
|
+
this.mode = "unknown";
|
|
33
|
+
}
|
|
34
|
+
clear() {
|
|
35
|
+
this.mode = "unknown";
|
|
36
|
+
this.buffer = Buffer.alloc(0);
|
|
37
|
+
}
|
|
38
|
+
processChunk(chunk, handlers) {
|
|
39
|
+
if (chunk.length === 0) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
43
|
+
while (true) {
|
|
44
|
+
try {
|
|
45
|
+
if (this.mode === "unknown") {
|
|
46
|
+
const detected = this.detectMode();
|
|
47
|
+
if (!detected) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.mode = detected;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const modeBefore = this.mode;
|
|
54
|
+
const message = this.mode === "content-length"
|
|
55
|
+
? this.readContentLengthMessage()
|
|
56
|
+
: this.readLineDelimitedMessage();
|
|
57
|
+
if (!message) {
|
|
58
|
+
if (this.mode !== modeBefore) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
handlers.onFrame({
|
|
64
|
+
message,
|
|
65
|
+
mode: this.mode
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (caughtError) {
|
|
69
|
+
this.mode = "unknown";
|
|
70
|
+
handlers.onError(asError(caughtError));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
detectMode() {
|
|
75
|
+
while (this.buffer.length > 0) {
|
|
76
|
+
if (this.buffer[0] === 0x0a) {
|
|
77
|
+
this.buffer = this.buffer.subarray(1);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (this.buffer.length >= 2 && this.buffer[0] === 0x0d && this.buffer[1] === 0x0a) {
|
|
81
|
+
this.buffer = this.buffer.subarray(2);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
if (this.buffer.length === 0) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
const prefix = this.buffer
|
|
90
|
+
.subarray(0, Math.min(this.buffer.length, 32))
|
|
91
|
+
.toString("utf8")
|
|
92
|
+
.toLowerCase();
|
|
93
|
+
if (prefix.startsWith("content-length")) {
|
|
94
|
+
return "content-length";
|
|
95
|
+
}
|
|
96
|
+
const firstNewline = this.buffer.indexOf(0x0a);
|
|
97
|
+
if (firstNewline === -1) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const firstLine = this.buffer.subarray(0, firstNewline).toString("utf8").replace(/\r$/, "");
|
|
101
|
+
if (/^\s*content-length\s*:/i.test(firstLine)) {
|
|
102
|
+
return "content-length";
|
|
103
|
+
}
|
|
104
|
+
return "line";
|
|
105
|
+
}
|
|
106
|
+
readLineDelimitedMessage() {
|
|
107
|
+
while (true) {
|
|
108
|
+
const newlineIndex = this.buffer.indexOf(0x0a);
|
|
109
|
+
if (newlineIndex === -1) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const line = this.buffer.subarray(0, newlineIndex).toString("utf8").replace(/\r$/, "");
|
|
113
|
+
this.buffer = this.buffer.subarray(newlineIndex + 1);
|
|
114
|
+
if (line.trim().length === 0) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (/^\s*content-length\s*:/i.test(line)) {
|
|
118
|
+
const separator = this.buffer.length > 0 && this.buffer[0] === 0x0d ? "\r\n" : "\n";
|
|
119
|
+
this.buffer = Buffer.concat([Buffer.from(`${line}${separator}`, "utf8"), this.buffer]);
|
|
120
|
+
this.mode = "content-length";
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return parseJsonRpcMessage(line);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
readContentLengthMessage() {
|
|
127
|
+
const headerBoundary = findHeaderBoundary(this.buffer);
|
|
128
|
+
if (!headerBoundary) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const headersRaw = this.buffer.subarray(0, headerBoundary.index).toString("utf8");
|
|
132
|
+
const headerLines = headersRaw
|
|
133
|
+
.split(/\r?\n/)
|
|
134
|
+
.map((line) => line.trim())
|
|
135
|
+
.filter((line) => line.length > 0);
|
|
136
|
+
let contentLength;
|
|
137
|
+
for (const headerLine of headerLines) {
|
|
138
|
+
const separatorIndex = headerLine.indexOf(":");
|
|
139
|
+
if (separatorIndex === -1) {
|
|
140
|
+
this.buffer = this.buffer.subarray(headerBoundary.index + headerBoundary.delimiterBytes);
|
|
141
|
+
throw new Error(`Malformed header line: ${headerLine}`);
|
|
142
|
+
}
|
|
143
|
+
const headerName = headerLine.slice(0, separatorIndex).trim().toLowerCase();
|
|
144
|
+
const headerValue = headerLine.slice(separatorIndex + 1).trim();
|
|
145
|
+
if (headerName === "content-length") {
|
|
146
|
+
const parsed = Number.parseInt(headerValue, 10);
|
|
147
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
148
|
+
this.buffer = this.buffer.subarray(headerBoundary.index + headerBoundary.delimiterBytes);
|
|
149
|
+
throw new Error(`Invalid Content-Length header value: ${headerValue}`);
|
|
150
|
+
}
|
|
151
|
+
contentLength = parsed;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (contentLength === undefined) {
|
|
155
|
+
this.buffer = this.buffer.subarray(headerBoundary.index + headerBoundary.delimiterBytes);
|
|
156
|
+
throw new Error("Missing Content-Length header.");
|
|
157
|
+
}
|
|
158
|
+
const messageStart = headerBoundary.index + headerBoundary.delimiterBytes;
|
|
159
|
+
const frameEnd = messageStart + contentLength;
|
|
160
|
+
if (this.buffer.length < frameEnd) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
const body = this.buffer.subarray(messageStart, frameEnd).toString("utf8");
|
|
164
|
+
this.buffer = this.buffer.subarray(frameEnd);
|
|
165
|
+
return parseJsonRpcMessage(body);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=json-rpc-framing.js.map
|
|
@@ -43,9 +43,17 @@ export function applyMappingPipeline(input) {
|
|
|
43
43
|
requestedMapping: input.requestedMapping,
|
|
44
44
|
target: input.target,
|
|
45
45
|
origin: input.resolved.origin,
|
|
46
|
+
artifactOrigin: input.resolved.origin,
|
|
46
47
|
binaryJarPath: input.resolved.binaryJarPath,
|
|
47
48
|
sourceJarPath: input.resolved.sourceJarPath,
|
|
48
|
-
nextAction: "Provide a source-backed artifact (source jar) or use mapping=obfuscated."
|
|
49
|
+
nextAction: "Provide a source-backed artifact (source jar) or use mapping=obfuscated.",
|
|
50
|
+
suggestedCall: {
|
|
51
|
+
tool: "resolve-artifact",
|
|
52
|
+
params: {
|
|
53
|
+
target: input.target,
|
|
54
|
+
mapping: "obfuscated"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
49
57
|
}
|
|
50
58
|
});
|
|
51
59
|
}
|
|
@@ -46,6 +46,8 @@ export type SymbolResolutionOutput = {
|
|
|
46
46
|
status: SymbolResolutionStatus;
|
|
47
47
|
resolvedSymbol?: SymbolReference;
|
|
48
48
|
candidates: Array<SymbolReference & Pick<MappingLookupCandidate, "matchKind" | "confidence">>;
|
|
49
|
+
candidateCount: number;
|
|
50
|
+
candidatesTruncated?: boolean;
|
|
49
51
|
warnings: string[];
|
|
50
52
|
provenance?: MappingLookupProvenance;
|
|
51
53
|
ambiguityReasons?: string[];
|
|
@@ -56,6 +58,7 @@ export type FindMappingInput = {
|
|
|
56
58
|
name: string;
|
|
57
59
|
owner?: string;
|
|
58
60
|
descriptor?: string;
|
|
61
|
+
signatureMode?: "exact" | "name-only";
|
|
59
62
|
sourceMapping: SourceMapping;
|
|
60
63
|
targetMapping: SourceMapping;
|
|
61
64
|
sourcePriority?: MappingSourcePriority;
|
|
@@ -63,6 +66,7 @@ export type FindMappingInput = {
|
|
|
63
66
|
ownerHint?: string;
|
|
64
67
|
descriptorHint?: string;
|
|
65
68
|
};
|
|
69
|
+
maxCandidates?: number;
|
|
66
70
|
};
|
|
67
71
|
export type FindMappingOutput = SymbolResolutionOutput;
|
|
68
72
|
export type EnsureMappingAvailableInput = {
|
|
@@ -84,6 +88,7 @@ export type ResolveMethodMappingExactInput = {
|
|
|
84
88
|
sourceMapping: SourceMapping;
|
|
85
89
|
targetMapping: SourceMapping;
|
|
86
90
|
sourcePriority?: MappingSourcePriority;
|
|
91
|
+
maxCandidates?: number;
|
|
87
92
|
};
|
|
88
93
|
export type ResolveMethodMappingExactOutput = SymbolResolutionOutput;
|
|
89
94
|
export type ClassApiMatrixKind = "class" | "field" | "method";
|
|
@@ -93,6 +98,7 @@ export type ClassApiMatrixInput = {
|
|
|
93
98
|
classNameMapping: SourceMapping;
|
|
94
99
|
sourcePriority?: MappingSourcePriority;
|
|
95
100
|
includeKinds?: ClassApiMatrixKind[];
|
|
101
|
+
maxRows?: number;
|
|
96
102
|
};
|
|
97
103
|
export type ClassApiMatrixEntry = {
|
|
98
104
|
symbol: string;
|
|
@@ -115,6 +121,8 @@ export type ClassApiMatrixOutput = {
|
|
|
115
121
|
classNameMapping: SourceMapping;
|
|
116
122
|
classIdentity: Partial<Record<SourceMapping, string>>;
|
|
117
123
|
rows: ClassApiMatrixRow[];
|
|
124
|
+
rowCount: number;
|
|
125
|
+
rowsTruncated?: boolean;
|
|
118
126
|
warnings: string[];
|
|
119
127
|
ambiguousRowCount?: number;
|
|
120
128
|
};
|
|
@@ -128,6 +136,7 @@ export type SymbolExistenceInput = {
|
|
|
128
136
|
sourcePriority?: MappingSourcePriority;
|
|
129
137
|
nameMode?: "fqcn" | "auto";
|
|
130
138
|
signatureMode?: "exact" | "name-only";
|
|
139
|
+
maxCandidates?: number;
|
|
131
140
|
};
|
|
132
141
|
export type SymbolExistenceOutput = SymbolResolutionOutput;
|
|
133
142
|
export declare class MappingService {
|