Atlas / MCP servers / monteslu / romdevtools

romdevtoolsCAUTION

mcp/monteslu/romdev

suite of tools and mcp server for quickly making retro console roms and romhacks

Verdict
CAUTION
Grade
C
Trust score
73 /100
Exposed tools
44 33r · 11w · 0d
Transport
streamable-http
License
NOASSERTION
Stars
19
01

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 (pcmToBrr for SNES, wavToXgm2Pcm for 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
Read from source at commit 5ec16d6248f9OBSERVED · 2026-10-07
02

Connect

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-code
claude mcp add romdevtools --env XAUTHORITY=${XAUTHORITY} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "romdevtools": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "XAUTHORITY": "${XAUTHORITY}"
      }
    }
  }
}
03

Exposed tools (44)

33 read · 11 write · 0 destructive.

ToolRiskDescription
assembleSnippetreadUse this to assemble a tiny chunk of asm to raw bytes - no header/linker/segments, just the bytes
assetsreadConvert PNGs to platform tile formats, encode WAVs to BRR, scan ROMs to identify them.
audioDebugreadDebug sound / transcribe music on the running ROM.
backgroundreadBackground/tilemap inspection + render state, one tool keyed by
breakpointwriteSTOP-on-first dynamic breakpoints - run until a condition hits, then stop. One tool keyed by
buildreadCompile/assemble source for a target platform; one tool keyed by
cartreadCartridge container ops - identify / split / reassemble a ROM file.
catalogreadOrient yourself, keyed by
cheatswriteCheat lookup / search / apply / create for the loaded ROM.
cpureadRead or drive a CPU, one tool keyed by
decompreadMatching decompilation: recover C that compiles to the ORIGINAL bytes with the project
disasmreadDisassemble code - raw bytes, a whole ROM (mapper-aware), a full re-buildable project, or find references to
encodeArtreadEncode a PNG into a platform
encodeAudioreadEncode an external audio clip into a platform
examplesreadThe example-game library - one buildable, rendering starting point per platform×genre, and the ONLY way to start
feedbackreadReport a romdev defect or a token sink you actually hit, keyed by
filesreadGeneric file I/O on disk for arbitrary agent artifacts (a generated PNG, a backup ROM, a notes file, a work-in-progress source).
framereadAdvance the emulator and capture frames.
hostreadEmulator host lifecycle.
importArtwriteImport art from an editor file or a source ROM into the target platform
inputreadDrive controllers, press buttons, learn each platform
inspectreadmemory regions, CPU and sound-chip state, sprites, palettes, tilemaps
loadMediareadLoad a ROM/disk/tape/program into a fresh host - resolves the libretro core automatically.
memorywriteRead/write platform memory regions: system_ram, save_ram, VRAM, plus platform extras (NES OAM, SNES CGRAM/ARAM/FillRAM).
packreadPackage a native-runtime game
palettereadColor palettes - read the running ROM
platformwritePlatform/toolchain/docs discovery - what romdev can run and how.
platformsreadDiscover supported platforms, their cores, toolchains, and language matrices.
playtestreadShow the loaded ROM to a HUMAN in a native SDL window, one tool keyed by
projectreadThe example-game library (fork/list/show) + starter snippets per platform.
recordSessionwriteRun 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).
regressionreadCheckpoint-based golden regression harness - prove a change didn
reverse-engineerwritevalue search, write/read watchpoints, disassembly, control-flow graphs, cross-references, Ghidra pseudocode, live jumptable recovery
romPatchwritePatch / re-inject / inspect a ROM file on disk, one tool keyed by
runwriteLoad ROMs, step frames, take screenshots (PNG or ANSI/chafa for text-only agents), query host status.
runUntilreadStep the emulator forward until a condition holds, or until maxFrames is reached. Use this instead of polling stepFrames + readMemory yourself for
spritesreadHardware-sprite (OAM/SAT) inspection + the meta-sprite asset pipeline, one tool keyed by
statewriteSave/load emulator snapshots, dump raw savestates for forensic inspection.
symbolsreadSymbol/linker-map lookups for C/asm-built ROMs - resolve names ↔ addresses and see the memory layout.
textreadCustom-font text workflow for ROM hacking - learn a game
tilesreadDECODE & render tile / CHR / pattern-table / VRAM bytes, one tool keyed by
videoDebugreadDecode the running ROM
wasmreadInspect a WASM-runtime cart (wasmcart) - the introspection an emulator can
watchwriteLOG-ALL dynamic tracing - run N frames and log EVERY hit (not stop-on-first; for stop-on-first use
04

Trust audit

CAUTIONgrade C · trust 73/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codePASS
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (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)

MEDIUMInventory / provenance · inv.binary · CWE-1104
packages/romdev-audio-resampler/resampler.wasm
resampler.wasm
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
packages/romdev-core-bluemsx/bios/Machines/MSX - C-BIOS/cbios_logo_msx1.rom
cbios_logo_msx1.rom
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
packages/romdev-core-bluemsx/bios/Machines/MSX - C-BIOS/cbios_main_msx1.rom
cbios_main_msx1.rom
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
packages/romdev-core-bluemsx/bios/Machines/MSX2 - C-BIOS/cbios_logo_msx2.rom
cbios_logo_msx2.rom
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
packages/romdev-core-bluemsx/bios/Machines/MSX2 - C-BIOS/cbios_main_msx2.rom
cbios_main_msx2.rom
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/romdevtools/src/decomp/project.js:30
const h = createHash("sha1");
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/romdevtools/src/decomp/project.js:357
return { bytes: out, sha1: createHash("sha1").update(out).digest("hex"), preview: out.subarray(0, 16).toString("hex") };
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/romdevtools/src/decomp/runtime.js:91
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),
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/romdevtools/src/decomp/smoke.js:74
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("
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/romdevtools/test/dreamcast-jit-perf.js:42
return crypto.createHash("md5")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/romdevtools/scripts/build-z80-binutils-wasm.sh:25
PKG_OUT="$HERE/../../romdev-toolchain-sdcc/wasm"
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/romdevtools/scripts/build-z80-binutils-wasm.sh:26
BUILD="${BUILD_DIR:-$HERE/../../../.z80build}"
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/romdevtools/src/analysis/recompile/emit-65816.js:12
import { NES_REGISTERS } from "../../platforms/common/registers.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/romdevtools/src/analysis/recompile/export-z80-ir.js:6
import { runObjdump } from "../../toolchains/objdump.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/romdevtools/src/analysis/recompile/lift-6502.js:14
import { NES_REGISTERS } from "../../platforms/common/registers.js";
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:147
npx romdevtools      # tool server on http://127.0.0.1:7331/mcp
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:150
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
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:152
Then register `http://127.0.0.1:7331/mcp` (streamable-HTTP transport) with your agent:
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:157
claude mcp add --transport http romdev http://127.0.0.1:7331/mcp
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.md:170
"url": "http://127.0.0.1:7331/mcp",
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/romdev-platform-gba/build/common/io.js:72
const bin = atob(data);
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/romdev-toolchain-m68k-gcc/build/common/io.js:72
const bin = atob(data);
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/romdevtools/src/toolchains/common/io.js:72
const bin = atob(data);
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@eslint/js, eslint, globals
Why it matters. 3 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/romdev-core-host/package.json
@monteslu/chafa-wasm, native-gles, pngjs, webgl-node
Why it matters. 4 dependency range(s) float
Fix. pin exact versions or ship a lockfile

Gates applied: no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha 5ec16d6248f9full audit observations/trust-audit/mcp-server/monteslu__romdev.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-075ec16d6248f9CAUTIONC73first audit
06

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.

Advertisement