Look up Mojang official names directly from piston-meta
mc_mojang_mappingsFetches and searches Mojang's client mappings for Minecraft versions that linkie cannot load, such as the 26.1 lineage. Verifies class, method, or field names directly from piston-meta.mojang.com.
Instructions
Bypasses linkie and fetches Mojang's client_mappings.txt straight from piston-meta.mojang.com, parses the proguard format, and searches it. Use this for any version linkie can't load — most importantly the 26.1 lineage (26.1, 26.1.1, 26.1.2) which linkie advertises but 500s on. Also useful when you want to verify a name against Mojang directly. First call for a version downloads the mapping (multi-MB) and caches it in-process; subsequent calls are instant.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| version | Yes | Minecraft version id, e.g. '26.1.2', '1.21.11' | |
| query | Yes | Class/method/field name (or substring) to search for | |
| type | No | Filter. Default all. | |
| limit | No | Max hits. Default 25. |
Implementation Reference
- src/index.ts:804-865 (registration)Registration of the 'mc_mojang_mappings' tool via server.registerTool, including the inputSchema (version, query, type, limit) and the handler that calls getMappings and searchMojangMappings from mojang.ts.
server.registerTool( "mc_mojang_mappings", { title: "Look up Mojang official names directly from piston-meta", description: "Bypasses linkie and fetches Mojang's client_mappings.txt straight from " + "piston-meta.mojang.com, parses the proguard format, and searches it. " + "Use this for any version linkie can't load — most importantly the 26.1 " + "lineage (26.1, 26.1.1, 26.1.2) which linkie advertises but 500s on. " + "Also useful when you want to verify a name against Mojang directly. " + "First call for a version downloads the mapping (multi-MB) and caches " + "it in-process; subsequent calls are instant.", inputSchema: { version: z.string().describe("Minecraft version id, e.g. '26.1.2', '1.21.11'"), query: z.string().describe("Class/method/field name (or substring) to search for"), type: z.enum(["class", "method", "field", "all"]).optional().describe("Filter. Default all."), limit: z.number().int().positive().max(100).optional().describe("Max hits. Default 25."), }, }, async ({ version, query, type, limit }) => { try { const parsed = await getMappings(version); const hits = searchMojangMappings(parsed, query, { type, limit }); if (hits.length === 0) { return text(`No matches for "${query}" in Mojang mappings for ${version}.`); } const lines: string[] = [ `# ${hits.length} hit${hits.length === 1 ? "" : "s"} in Mojang mappings for ${version} (query: "${query}")`, "", ]; for (const h of hits) { if (h.type === "class") { lines.push(`- **class** \`${h.owner}\` obf: \`${h.obfuscated}\``); } else { lines.push( `- **${h.type}** \`${h.owner}#${h.name}\`` + (h.signature ? ` \`${h.signature}\`` : "") + ` obf: \`${h.obfuscated}\``, ); } } return text(lines.join("\n")); } catch (err) { if (err instanceof MojangVersionNotFoundError) { const recent = await listMojangVersions((id) => id.startsWith("26.") || id.startsWith("1.21")); return text( `${err.message}\n\nRecent 26.x / 1.21.x ids on piston-meta: ${recent.slice(0, 20).join(", ")}.`, ); } if (err instanceof MojangNoMappingsError) { return text( `${err.message}\n\n` + `**Workarounds for ${err.version}:**\n` + `- Try mc_list_versions to see which linkie namespaces have ingested this version.\n` + `- For class concepts whose names rarely change, mc_lookup_class is still useful (curated).\n` + `- The compiled client.jar at piston-data still ships — symbol extraction would require decompilation, which this server doesn't do.`, ); } return text(`Mojang mappings fetch failed: ${(err as Error).message}`); } }, ); - src/mojang.ts:73-82 (handler)getMappings() - Core handler function that fetches+parses client_mappings.txt for a given Minecraft version. Uses in-process cache and delegates to fetchAndParse which downloads from piston-meta.mojang.com and parses the proguard format.
export function getMappings(version: string): Promise<ParsedMappings> { const cached = mappingCache.get(version); if (cached) return cached; const promise = fetchAndParse(version).catch((err) => { mappingCache.delete(version); // don't poison cache on transient failure throw err; }); mappingCache.set(version, promise); return promise; } - src/mojang.ts:224-285 (handler)searchMojangMappings() - Search function used by the tool handler. Performs substring-and-token search across parsed mappings for classes, methods, and fields with ranking by exact/prefix/substring match.
export function searchMojangMappings( parsed: ParsedMappings, query: string, opts: { limit?: number; type?: "class" | "method" | "field" | "all" } = {}, ): MojangSearchHit[] { const limit = opts.limit ?? 25; const type = opts.type ?? "all"; const q = query.toLowerCase(); const hits: MojangSearchHit[] = []; if (type === "class" || type === "all") { for (const [mapped, obf] of parsed.classes) { const simple = mapped.split(".").pop() ?? mapped; if (mapped.toLowerCase().includes(q) || simple.toLowerCase().includes(q)) { hits.push({ type: "class", owner: mapped, obfuscated: obf }); if (hits.length >= limit * 4) break; } } } if (type === "method" || type === "field" || type === "all") { outer: for (const [owner, bucket] of parsed.members) { if (type === "method" || type === "all") { for (const m of bucket.methods) { if (m.mappedName.toLowerCase().includes(q)) { hits.push({ type: "method", owner, name: m.mappedName, obfuscated: m.obfName, signature: `${m.mappedReturn} ${m.mappedName}(${m.mappedParams.join(", ")})`, }); if (hits.length >= limit * 4) break outer; } } } if (type === "field" || type === "all") { for (const f of bucket.fields) { if (f.mappedName.toLowerCase().includes(q)) { hits.push({ type: "field", owner, name: f.mappedName, obfuscated: f.obfName, signature: f.mappedType, }); if (hits.length >= limit * 4) break outer; } } } } } // Rank: exact-name > prefix > substring; classes and members interleave by score. const score = (h: MojangSearchHit): number => { const n = (h.name ?? h.owner.split(".").pop() ?? "").toLowerCase(); if (n === q) return 1000; if (n.startsWith(q)) return 500; return 100 - Math.abs(n.length - q.length); }; hits.sort((a, b) => score(b) - score(a)); return hits.slice(0, limit); } - src/mojang.ts:152-205 (helper)parseProguard() - Parses Mojang's proguard-format client_mappings.txt into ParsedMappings (classes Map and members Map). The proguard format maps Mojang names → obfuscated names.
export function parseProguard(version: string, text: string): ParsedMappings { const classes = new Map<string, string>(); const members = new Map<string, ClassMembers>(); let currentClass: string | null = null; let currentBucket: ClassMembers | null = null; // We split lines once. Files are large (multi-MB) but this is fine in Node. const lines = text.split("\n"); for (let i = 0; i < lines.length; i++) { const raw = lines[i]; if (!raw || raw.startsWith("#")) continue; if (raw[0] !== " " && raw[0] !== "\t") { // Class line: "<mapped> -> <obf>:" const m = raw.match(/^([^\s]+) -> ([^:]+):\s*$/); if (!m) continue; currentClass = m[1]; const obf = m[2]; classes.set(currentClass, obf); currentBucket = { fields: [], methods: [] }; members.set(currentClass, currentBucket); continue; } if (!currentBucket || !currentClass) continue; const body = raw.trimStart(); // Method: "12:120:void name(int,int) -> a" OR "void name(int,int) -> a" const methodMatch = body.match( /^(?:(\d+):(\d+):)?([^\s]+) ([^\s(]+)\(([^)]*)\) -> ([^\s]+)$/, ); if (methodMatch) { const [, start, end, retType, name, paramsRaw, obf] = methodMatch; const params = paramsRaw ? paramsRaw.split(",") : []; currentBucket.methods.push({ mappedName: name, mappedReturn: retType, mappedParams: params, obfName: obf, lineRange: start && end ? `${start}:${end}` : undefined, }); continue; } // Field: "int experience -> bM" const fieldMatch = body.match(/^([^\s]+) ([^\s]+) -> ([^\s]+)$/); if (fieldMatch) { currentBucket.fields.push({ mappedType: fieldMatch[1], mappedName: fieldMatch[2], obfName: fieldMatch[3], }); } } return { version, classes, members }; } - src/index.ts:58-65 (schema)Import of types/functions used by mc_mojang_mappings: getMappings, searchMojangMappings, reverseMojangLookup, listMojangVersions, MojangVersionNotFoundError, MojangNoMappingsError from mojang.ts.
import { getMappings, searchMojangMappings, reverseMojangLookup, listMojangVersions, MojangVersionNotFoundError, MojangNoMappingsError, } from "./mojang.js";