modforge

modforge

Provides deterministic, audit-chain-backed Minecraft symbol migration and version-truth queries over MCP for AI assistants, enabling grounded rename resolution and API diffs without hallucination.

Category
Visit Server

README

<img src="https://raw.githubusercontent.com/champmk/modforge/main/assets/banner.svg" alt="ModForge" width="100%">

The deterministic cross-version migration engine for Minecraft mods.

CI npm license: MIT node >= 24

ModForge computes mod migrations instead of guessing at them: it chains your yarn-era or mojmap symbols through the real mapping artifacts, verifies every result against the actual target-version jar, and labels every finding EXACT, CANDIDATE, or UNRESOLVED -- with the full audit chain that proves it. The timing is not academic: Minecraft 1.21.11 (Dec 2025) was the last obfuscated version with yarn/mojmap mappings, 26.1 (Mar 2026) shipped real source names in the jar, and the game now breaks its API on quarterly drops -- so every mod written before the boundary needs a port, and every quarter brings another one.

Why this exists

Porting a mod across the 26.1 boundary means translating thousands of symbols through multiple mapping layers, catching the renames Mojang made along the way, and fixing mixin targets that fail silently at runtime. The official advice is to keep two workspaces open and diff by eye. That does not scale to a mod with 450 Minecraft references, and it definitely does not scale four times a year.

The tempting shortcut is to ask an LLM. But renames are exactly where language models fail worst: a model will confidently map GuiGraphics to whatever looks plausible from its training data, and a confidently wrong rename costs more than no answer at all -- it compiles into a subtle runtime bug or sends you debugging a class that never existed.

The fix is deterministic grounding. ModForge never invents a name. Every EXACT result is a mechanical join through the real yarn, intermediary, and mojmap files, verified by name-and-descriptor lookup against the actual target jar. When the data cannot prove an answer, ModForge says so, with the precise reason. The same engine is exposed over MCP, so AI assistants can ask it for version-truth instead of hallucinating.

Quickstart

Requires Node >= 24 (TypeScript runs natively -- no build step).

npx modforge versions
npx modforge bridge --from 1.21.11 --to 26.1.2 path/to/your-mod/src/main/java

The first run downloads the needed mappings and jars from official sources, sha1-verifies them, and caches under ~/.modforge/cache. Then you get a report like this (excerpt from a real run on AppleSkin):

EXACT
  L5:8 import class net/minecraft/entity/player/PlayerEntity
    → net/minecraft/world/entity/player/Player
    reason: Deterministic chain resolved and class exists in 26.1.2-client.
    · yarn: named net/minecraft/entity/player/PlayerEntity → intermediary net/minecraft/class_1657
    · intermediary: net/minecraft/class_1657 → official ddm
    · mojmap: obf ddm → source net/minecraft/world/entity/player/Player
    · target(26.1.2-client): class present

CANDIDATE
  L4:8 import class net/minecraft/client/gui/DrawContext
    →? net/minecraft/client/gui/GuiGraphicsExtractor (score 0.9)
    2 inner classes (RenderingTextCollector, ScissorStack) matched bijectively
    with identical inner names — containment evidence for the outer rename.
    Structural evidence only — a rename cannot be proven; verify before applying.
    reason: Chain resolved to net/minecraft/client/gui/GuiGraphics, but that class
    does not exist in 26.1.2-client — it was removed or renamed after the era
    boundary. The rename layer supplies a grounded candidate — never auto-applied.

UNRESOLVED
  L67:37 member-instance method net/minecraft/server/world/ServerWorld#getPlayers
    reason: yarn has 2 overloads of getPlayers on net/minecraft/server/world/ServerWorld,
    none with 0 parameters (callsite arity) — varargs or mis-counted arity; not guessing.

453 references — EXACT 402 · CANDIDATE 29 · UNRESOLVED 22
note: CANDIDATE items need your judgment; UNRESOLVED items are honest unknowns, not failures.

(Excerpt trimmed from a real run; audit-chain lines appear on every finding.)

Add --json for a stable machine-readable schema, or --out report.md for markdown.

Commands

Command What it does
modforge bridge --from <v> --to <v> [--namespace named|source] <src-dir> [--json] [--out report.md] [--apply] Era migration report: resolves every Minecraft reference in your source tree to its target-version name, with audit chains. --apply writes the EXACT rewrites to disk (originals backed up under .modforge-backup/); CANDIDATE and UNRESOLVED are never touched.
modforge delta --from <v> --to <v> [--json] [--out delta.md] Exact API surface diff between any two game versions -- the "what breaks in 26.2" report, computable the minute a version ships (--out writes the publishable markdown).
modforge gradle-migrate <dir> [--apply] Mechanical build-script migration (loom plugin id, mappings block, dependency forms, Java 25); dry-run by default, EXACT-tier rewrites only with --apply.
modforge mixin-check --target <v> <src-dir> Verifies @Mixin targets and member references against the target version's jar.
modforge versions Shows the latest release/snapshot and the era boundary.

Every command is CI-friendly: deterministic output, exit 0 on success (UNRESOLVED findings are a successful result), exit 2 on usage errors, exit 1 on operational failures.

The honesty taxonomy

Every finding carries exactly one verdict. This is the core of the product.

Verdict Meaning
EXACT Every join hop is deterministic and the result is verified against the target jar by name and descriptor. Safe to auto-apply.
CANDIDATE Structurally evidenced (bijective rename matching, descriptor fingerprints) and shown with its evidence. Never auto-applied.
UNRESOLVED An honest unknown with the precise reason. A refusal is a successful result, not an error.

Renames in an unobfuscated world are structurally unprovable, so ModForge never asserts one -- it shows you the evidence and the ranking. A confidently wrong answer is treated as a P0 bug. Every resolution carries its full audit chain: every join hop that produced it.

MCP server

ModForge ships a dependency-free MCP server (stdio, spec 2025-11-25) so AI coding assistants can query the engine for grounded version-truth instead of guessing renames. The honesty taxonomy travels on the wire: UNRESOLVED is a successful result, never an error response.

Five tools:

  • modforge_resolve_symbol -- resolve a single class or member across versions
  • modforge_bridge_report -- full bridge report for a source tree
  • modforge_api_delta -- API surface diff between two versions
  • modforge_check_mixin_target -- verify a mixin target against a version
  • modforge_versions -- version metadata and the era boundary

Install into Claude Code:

npm install -g modforge
claude mcp add modforge -- modforge-mcp

(From a repo clone instead: claude mcp add modforge -- node <abs-path>/src/mcp/server.ts.)

Any MCP-capable client works the same way -- Cursor, Copilot, or your own agent: point it at src/mcp/server.ts over stdio.

Validated against reality

Correctness is the product, so ModForge is scored against real artifacts and real human work, not synthetic benchmarks:

  • The classfile parser (every constant-pool tag through Java 25, zero dependencies) reads all 10,152 classes of the 26.1.2 client jar in ~500ms with zero errors.
  • Bulk-bridging the entire 1.21.11 class surface to 26.1.2 resolves 91.5% of classes EXACT in 16ms.
  • A real-mod run on AppleSkin: 453 references -> 402 EXACT, 29 CANDIDATE, 22 UNRESOLVED -- and every UNRESOLVED is a genuine same-arity overload where guessing would be wrong.
  • The standing validation gate scores ModForge's EXACT set against AppleSkin's actual human-written port commit: 100% EXACT precision -- and the engine surfaced a hotfix rename (GuiGraphics -> GuiGraphicsExtractor in 26.1.2) that the merged human port had missed.
  • 30/30 tests passing, strict TypeScript (tsc) clean across the repo.

Any EXACT that contradicts what human porters actually did is a release blocker.

How it works

Two engines share one honesty contract. The Era Bridge chains yarn-named or mojmap-source symbols through yarn tiny-v2 -> intermediary tiny -> ProGuard mojmap, then verifies each result against the parsed target jar (name + descriptor join), walking the old jar's class hierarchy for inherited members and translating descriptors to disambiguate overloads. The API Delta engine parses two game jars with ModForge's own dependency-free classfile parser and diffs the API surface directly; renames ship only as evidence-labeled bijective candidates. All mappings and jars are fetched client-side from Mojang's official endpoints at runtime, sha1-verified, and cached -- never redistributed. Full details: docs/ARCHITECTURE.md and docs/SPEC.md.

Roadmap

  • Instruction-level mixin @At verification (a signature can match while the targeted instruction is gone)
  • NeoForge convenience flow (mojmap-input mods skip the yarn hops)
  • Expanded validation corpus across more real ports

Contributing and license

Contributions welcome -- see CONTRIBUTING.md. Corpus cases where ModForge got something wrong are especially valuable: a confidently wrong answer is the one bug class treated as P0.

Licensed under MIT.

ModForge is built and maintained by Champ-Pacifique Mukiza. I build with AI assistance and review, test, and own every line.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured