romdevtoolsCAUTION
suite of tools and mcp server for quickly making retro console roms and romhacks
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Vibe-code real retro games. One command, and your coding agent can make actual working ROMs for NES, SNES, Game Boy, Genesis, Atari, Commodore 64, and more - that run on RetroArch, native emulators, flash carts, and real hardware. No SDK installs. No emulator setup. No PATH fiddling. No "this only works on Linux."
npx romdevtools
That's the whole setup. Everything - emulators, assemblers, C compilers, starter libraries, example projects, hardware reference docs - ships as bundled WebAssembly and data via npm. Same on Linux, Windows, and macOS (Node 24+).
Features
You (or your coding assistant, over MCP / plain HTTP) get a tool surface for the full homebrew loop:
- Building - bundled per-platform toolchains (cc65, SDCC, RGBDS, asar, vasm, SGDK, PVSnesLib, libtonc, ...) compiled to WebAssembly. The agent writes source, compiles it, and gets a real ROM.
- Asset conversion - turn external art and audio into native data without leaving the server: PNG → platform tiles/tilemaps (
convertImageToTiles,imageToTilemap- row-major or hardware sprite order), PNG quantize-to-palette, sprite-sheet/Aseprite/GIF loaders, and audio importers (pcmToBrrfor SNES,wavToXgm2Pcmfor Genesis XGM2 PCM). Path-in, native-data-out. - Running - load the ROM into an emulated console (libretro cores as WASM) and step through it frame by frame.
- Seeing - capture the framebuffer as a PNG and hand it to the agent.
- Driving - emit controller input, run input scripts, replay sequences.
- Inspecting - read CPU/video/save RAM, watch memory, disassemble, inspect sprites/palettes/tilemaps, read CPU + sound-chip state.
- Reverse-engineering & romhacking - a full RE toolkit for modifying existing games: iterative value search (
memory({op:'search'})→memory({op:'searchNext'}), the Cheat-Engine loop),memory({op:'classify'})(is this "table" really ASCII?),breakpoint({on:'write'})(the exact inst
5ec16d6248f9OBSERVED · 2026-10-07Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add romdevtools --env XAUTHORITY=${XAUTHORITY} -- npx -y [email protected]{
"mcpServers": {
"romdevtools": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"XAUTHORITY": "${XAUTHORITY}"
}
}
}
}Exposed tools (44)
33 read · 11 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
assembleSnippet | read | Use this to assemble a tiny chunk of asm to raw bytes - no header/linker/segments, just the bytes |
assets | read | Convert PNGs to platform tile formats, encode WAVs to BRR, scan ROMs to identify them. |
audioDebug | read | Debug sound / transcribe music on the running ROM. |
background | read | Background/tilemap inspection + render state, one tool keyed by |
breakpoint | write | STOP-on-first dynamic breakpoints - run until a condition hits, then stop. One tool keyed by |
build | read | Compile/assemble source for a target platform; one tool keyed by |
cart | read | Cartridge container ops - identify / split / reassemble a ROM file. |
catalog | read | Orient yourself, keyed by |
cheats | write | Cheat lookup / search / apply / create for the loaded ROM. |
cpu | read | Read or drive a CPU, one tool keyed by |
decomp | read | Matching decompilation: recover C that compiles to the ORIGINAL bytes with the project |
disasm | read | Disassemble code - raw bytes, a whole ROM (mapper-aware), a full re-buildable project, or find references to |
encodeArt | read | Encode a PNG into a platform |
encodeAudio | read | Encode an external audio clip into a platform |
examples | read | The example-game library - one buildable, rendering starting point per platform×genre, and the ONLY way to start |
feedback | read | Report a romdev defect or a token sink you actually hit, keyed by |
files | read | Generic file I/O on disk for arbitrary agent artifacts (a generated PNG, a backup ROM, a notes file, a work-in-progress source). |
frame | read | Advance the emulator and capture frames. |
host | read | Emulator host lifecycle. |
importArt | write | Import art from an editor file or a source ROM into the target platform |
input | read | Drive controllers, press buttons, learn each platform |
inspect | read | memory regions, CPU and sound-chip state, sprites, palettes, tilemaps |
loadMedia | read | Load a ROM/disk/tape/program into a fresh host - resolves the libretro core automatically. |
memory | write | Read/write platform memory regions: system_ram, save_ram, VRAM, plus platform extras (NES OAM, SNES CGRAM/ARAM/FillRAM). |
pack | read | Package a native-runtime game |
palette | read | Color palettes - read the running ROM |
platform | write | Platform/toolchain/docs discovery - what romdev can run and how. |
platforms | read | Discover supported platforms, their cores, toolchains, and language matrices. |
playtest | read | Show the loaded ROM to a HUMAN in a native SDL window, one tool keyed by |
project | read | The example-game library (fork/list/show) + starter snippets per platform. |
recordSession | write | Run the loaded ROM for N frames, sampling screenshots and/or memory every sampleEvery frames. Returns a timeline the agent can analyze. Inputs are either held for the whole session (holdInputs) or scripted as {atFrame, ports} entries each held until the next (inputScript). |
regression | read | Checkpoint-based golden regression harness - prove a change didn |
reverse-engineer | write | value search, write/read watchpoints, disassembly, control-flow graphs, cross-references, Ghidra pseudocode, live jumptable recovery |
romPatch | write | Patch / re-inject / inspect a ROM file on disk, one tool keyed by |
run | write | Load ROMs, step frames, take screenshots (PNG or ANSI/chafa for text-only agents), query host status. |
runUntil | read | Step the emulator forward until a condition holds, or until maxFrames is reached. Use this instead of polling stepFrames + readMemory yourself for |
sprites | read | Hardware-sprite (OAM/SAT) inspection + the meta-sprite asset pipeline, one tool keyed by |
state | write | Save/load emulator snapshots, dump raw savestates for forensic inspection. |
symbols | read | Symbol/linker-map lookups for C/asm-built ROMs - resolve names ↔ addresses and see the memory layout. |
text | read | Custom-font text workflow for ROM hacking - learn a game |
tiles | read | DECODE & render tile / CHR / pattern-table / VRAM bytes, one tool keyed by |
videoDebug | read | Decode the running ROM |
wasm | read | Inspect a WASM-runtime cart (wasmcart) - the introspection an emulator can |
watch | write | LOG-ALL dynamic tracing - run N frames and log EVERY hit (not stop-on-first; for stop-on-first use |
Trust audit
CAUTIONgrade C · trust 73/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (6 observation(s))
- Network
- declared (9 observation(s))
- Shell
- declared (3 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (25)
resampler.wasm
cbios_logo_msx1.rom
cbios_main_msx1.rom
cbios_logo_msx2.rom
cbios_main_msx2.rom
const h = createHash("sha1");return { bytes: out, sha1: createHash("sha1").update(out).digest("hex"), preview: out.subarray(0, 16).toString("hex") };out.push({ vram: hx(vram), candidates: segs.length, loaded, partial, ramSha1: createHash("sha1").update(ram).digest("hex"), allZero: ram.every((b) => b === 0), matches: matches.slice(0, 4),results[side.name] = { load: { loaded: load?.loaded ?? null, core: load?.core ?? null }, checkpoint, png, width: img.width, height: img.height, pixelsSha1: createHash("sha1").update(img.data).digest("return crypto.createHash("md5")PKG_OUT="$HERE/../../romdev-toolchain-sdcc/wasm"
BUILD="${BUILD_DIR:-$HERE/../../../.z80build}"import { NES_REGISTERS } from "../../platforms/common/registers.js";import { runObjdump } from "../../toolchains/objdump.js";import { NES_REGISTERS } from "../../platforms/common/registers.js";npx romdevtools # tool server on http://127.0.0.1:7331/mcp
The first run downloads the cores/toolchains; later runs start instantly from the npm cache. An **optional observer** for watching tool calls live is at `http://127.0.0.1:7331/livestream` - purely for
Then register `http://127.0.0.1:7331/mcp` (streamable-HTTP transport) with your agent:
claude mcp add --transport http romdev http://127.0.0.1:7331/mcp
"url": "http://127.0.0.1:7331/mcp",
const bin = atob(data);
const bin = atob(data);
const bin = atob(data);
@eslint/js, eslint, globals
@monteslu/chafa-wasm, native-gles, pngjs, webgl-node
Gates applied: no_behavioural_pass.
5ec16d6248f9full audit observations/trust-audit/mcp-server/monteslu__romdev.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-07 | 5ec16d6248f9 | CAUTION | C | 73 | first audit |
Questions
What is the romdevtools MCP server?
suite of tools and mcp server for quickly making retro console roms and romhacks
What tools does romdevtools expose?
44 in total: 33 read-only, 11 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is romdevtools safe to connect to an agent?
With care. The audit graded it C (73/100) and found 25 things worth knowing before you trust this server, listed below with the exact line each was found on.
What credentials does romdevtools need?
It reads XAUTHORITY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does romdevtools run?
It speaks streamable-http, so it runs as a service you connect to over the network. It is published on npm as romdevtools at 0.149.1.
How current is this page?
The grade is for one exact copy of the source (5ec16d6248f9), read on 2026-10-07. The repository is watched and re-audited when it changes.