zesarux-mcp
The ZEsarUX MCP server provides a comprehensive interface to control the ZEsarUX ZX Spectrum emulator via ZRCP, covering emulator management, debugging, memory operations, and more.
Emulator Lifecycle
Launch/kill the emulator, set machine type (48k, 128k, Pentagon, TBBlue, etc.), soft/hard reset, and retrieve emulator info (version, machine, OS, CPU core).
Memory Operations
Read (
peek), write (poke), and display (hexdump) emulated memory at specified addresses and optional memory zones. Read/write I/O ports.
CPU & Debugging
Get/set Z80 registers (full set including alternates, IX/IY/PC/SP/I/R)
Step into or step over instructions (
cpu_step)Disassemble Z80 code from any address
CPU execution history (ring buffer of recent PC traces)
Code coverage tracking
CPU transaction log (configurable fields, written to file)
T-state counter (read or reset)
Extended stack (read typed values)
Breakpoints
List, set (with conditions, pass counts, and fire actions for execute/memory/port events), and clear breakpoints.
File & Snapshot Operations
Smartload any file (tape, snapshot, etc.) with auto-detection
Save/load snapshot files (.zsf/.sna/.z80/.sp)
Access in-RAM Time Machine snapshots
Insert tape images
Screen
Save the current display to a .scr, .bmp, or .pbm file and return the file path.
Keyboard Input
Send a single key (tap/press/release) or type a full string character by character.
Assembly
Assemble Z80 instructions directly into memory at any address.
Audio & Media
Control the AY Player (load playlists, play/navigate tracks)
Reload the MMC/SD card image
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zesarux-mcp load tape games/jetpac.tap and execute"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ZEsarUX MCP Server
MCP server for ZEsarUX ZX Spectrum emulator using ZRCP protocol.
dtz-labs - Vibe coding 8-bit machines like there is no tomorrow

Features
13 tool categories with 50+ operations: machine control, PEEK/POKE, debugging (breakpoints, registers, disassembly), tape/disk loading, snapshots, keyboard input, assembly, and more.
Related MCP server: dos-mcp
Quick Start
Each client launches the server over stdio via npx — no clone or build needed.
The server then connects to ZEsarUX on ZRCP port 10000, auto-launching it for you
if nothing is listening there (on by default). Pick your client below; you'll
still need ZEsarUX installed — see Installation.
Claude Code
Register the server with one command:
claude mcp add zesarux -- npx -y @dtz-labs/zesarux-mcpAuto-launch is on by default. To disable it (only connect to a ZEsarUX you start yourself), set the env var:
claude mcp add zesarux --env ZESARUX_AUTOLAUNCH=false -- npx -y @dtz-labs/zesarux-mcpClaude Desktop
Edit claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json; Windows:
%APPDATA%\Claude\claude_desktop_config.json), then restart Claude Desktop:
{
"mcpServers": {
"zesarux": {
"command": "npx",
"args": ["-y", "@dtz-labs/zesarux-mcp"]
}
}
}Codex
Add to ~/.codex/config.toml:
[mcp_servers.zesarux]
command = "npx"
args = ["-y", "@dtz-labs/zesarux-mcp"]Opencode
Add to opencode.json (project) or ~/.config/opencode/opencode.json (global):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"zesarux": {
"type": "local",
"command": ["npx", "-y", "@dtz-labs/zesarux-mcp"],
"enabled": true
}
}
}Installation
1. Install ZEsarUX
macOS:
brew install zesarux
xattr -dr com.apple.quarantine /Applications/zesarux.appWhy the second command? macOS Gatekeeper tags any app that wasn't downloaded through the App Store (or signed/notarized by an identified developer) with a
com.apple.quarantineextended attribute. ZEsarUX isn't notarized, so the first time you launch it Gatekeeper refuses to open it ("can't be opened because Apple cannot check it for malicious software").xattr -drrecursively strips that attribute from the app bundle, telling Gatekeeper to trust it. This is needed because the Homebrew cask drops the.appinto/Applicationsbut cannot clear the quarantine flag for you.
Linux:
sudo apt-get install zesaruxOr download from: ZEsarUX releases
For Windows, compiling from source, and enabling ZRCP via the config file, see the full Installation & Configuration guide.
2. Start ZEsarUX with ZRCP
zesarux --enable-remoteprotocol --remoteprotocol-port 10000Or skip this step — the server auto-launches ZEsarUX for you by default (see Auto-launching ZEsarUX below).
3. Install the MCP Server
The server is published to npm as @dtz-labs/zesarux-mcp.
Your MCP client launches it on demand via npx (see Quick Start),
so nothing needs installing. To have it on your PATH as zesarux-mcp, install
it globally:
npm install -g @dtz-labs/zesarux-mcpgit clone https://github.com/dtz-labs/zesarux-mcp.git
cd zesarux-mcp
npm install
npm run build # produces dist/index.jsThen point your config at "command": "node", "args": ["/absolute/path/to/zesarux-mcp/dist/index.js"].
Environment variables
Variable | Default | Description |
|
| Host where ZEsarUX ZRCP is listening |
| (auto) | ZRCP port (matches |
|
|
|
|
| ZRCP request timeout, ms |
|
| Connection retry attempts |
|
| Reconnect automatically if the link drops |
|
| Start ZEsarUX automatically if it isn't reachable (set |
| (auto-detected) | Explicit path to the ZEsarUX binary |
| (none) | Extra args appended when launching (e.g. |
|
| How long to wait for the ZRCP port after launching, ms |
Auto-launching ZEsarUX
By default, when ZEsarUX isn't reachable on startup the server finds a local
ZEsarUX binary, launches it with --enable-remoteprotocol --remoteprotocol-port <port>, waits for the port, then connects. Set ZESARUX_AUTOLAUNCH=false to opt
out (only connect to a ZEsarUX you started yourself). An emulator the server
launched is terminated when the server stops; a ZEsarUX you started yourself is
left untouched. See
Installation & Configuration for
binary discovery order and headless use.
You can also control the emulator process at runtime with the launch_emulator
and kill_emulator tools (the latter only stops an emulator the server
started). And if a tool call fails because the connection dropped, the server
will — unless ZESARUX_AUTOLAUNCH=false — try once to relaunch ZEsarUX and
reconnect before retrying the call.
Running several servers (automatic ports)
In AUTO mode (auto-launch on, ZESARUX_PORT not set) the server picks the
first free port ≥ 10000 and launches its own ZEsarUX there. So you can
register several MCP servers with no port configuration at all and they fan out
automatically — the first takes 10000, the next 10001, then 10002, … each
with its own emulator:
claude mcp add zesarux-a -- npx -y @dtz-labs/zesarux-mcp
claude mcp add zesarux-b -- npx -y @dtz-labs/zesarux-mcpTo pin a server to a specific port — or to attach to an emulator that is
already running — set ZESARUX_PORT explicitly (e.g. ZESARUX_PORT=10000); the
server then uses exactly that port and does not scan. Automatic port selection
only happens in AUTO mode; with ZESARUX_AUTOLAUNCH=false the server just
connects to ZESARUX_PORT (default 10000).
Documentation
Documentation index - Start here
Installation & Configuration - Install ZEsarUX and the server
Configuring MCP Clients - Claude Desktop/Code, Codex, OpenCode, JetBrains
Available Tools - All tools with examples
Example Usage - Talk-to-it and quick call examples
Development - Build, structure, protocol mapping
Troubleshooting - Common problems
ZRCP Specification - Complete protocol reference
Quick Examples
// Reset and set machine
{"name": "reset_machine"}
{"name": "set_machine", "arguments": {"machine": "128k"}}
// Read/write memory
{"name": "peek", "arguments": {"address": "4000", "length": 256}}
{"name": "poke", "arguments": {"address": "4000", "value": [255, 0]}}
// Debugging
{"name": "get_registers"}
{"name": "set_breakpoint", "arguments": {"index": 1, "type": "execute", "address": "8000"}}
// Load tape
{"name": "load_file", "arguments": {"filename": "/path/game.tap"}}License
MIT
dtz-labs - Keeping 8-bit alive until 2065
Available Tools
34 toolsassembleA
Assemble a Z80 instruction at an address (ZRCP: assemble [address] [instruction])
Inputs: instruction (required), address.
ay_playerB
Run a command on the ZEsarUX AY Player (ZRCP ayplayer command [parameter]).
Inputs: command (required), parameter.
clear_breakpointA
Clear a breakpoint. ZEsarUX has no clear-single command: disabling the slot (disable-breakpoint) effectively clears it. Set mem_all=true to clear ALL memory breakpoints (clear-membreakpoints) instead.
Inputs: id, mem_all.
code_coverageB
CPU code-coverage control (ZRCP cpu-code-coverage). Enable/disable tracking, get covered addresses, or clear the list.
Inputs: action (required).
cpu_historyA
Query the CPU execution history ring buffer (ZRCP cpu-history). History must be enabled and started first (action=enable then action=start). action=get returns a recent PC trace.
Inputs: action, start, items.
cpu_stepC
Execute a single CPU instruction. Enters cpu-step mode first, then runs ZRCP cpu-step (or cpu-step-over when step_over is set).
Inputs: step_over.
cpu_transaction_logA
Configure the CPU transaction log (ZRCP cpu-transaction-log parameter value). Set logfile then enabled=yes to start. Output goes to the configured logfile; there is no read-back command.
Inputs: parameter (required), value (required).
disassembleA
Disassemble Z80 code (ZRCP disassemble [address] [lines]). Defaults to PC. Output is address + instruction (no byte column). Memory zone is selected separately via the active zone.
Inputs: address, length.
extended_stackA
Read the extended stack — typed values currently on the stack (ZRCP extended-stack get [index]). The extended stack must be enabled in ZEsarUX first. index defaults to SP.
Inputs: count, index.
get_emulator_infoB
Get emulator information via ZRCP. version→get-version, machine→get-current-machine, os→get-os, cpu_core→get-cpu-core-name; all→combines version + machine + os + buildnumber.
Inputs: details.
get_registersA
Get current CPU register values (Z80 main + alternate set, IX/IY/PC/SP/I/R, flag strings, interrupt mode, MEMPTR). Maps to ZRCP get-registers.
Inputs: no named parameters.
get_screenA
Capture the current screen. NOTE: ZRCP cannot return pixel data to the client, so this writes a file on the ZEsarUX host (via save-screen) and returns its path. Use get-ocr for on-screen text.
Inputs: format.
get_tstatesA
Get the T-state counter via ZRCP get-tstates. If reset is true, resets the PARTIAL counter (reset-tstates-partial) and returns it. ZEsarUX has no way to reset the main counter.
Inputs: reset.
hexdumpB
Display memory in hexadecimal + ascii (ZRCP hexdump)
Inputs: address, length, memory_zone.
kill_emulatorA
Stop the ZEsarUX emulator — but ONLY if this server started it. An externally-launched ZEsarUX is left untouched (you must stop it yourself).
Inputs: no named parameters.
launch_emulatorA
Start the ZEsarUX emulator process and connect to it. If ZEsarUX is already running/reachable, just connects. Locates the binary automatically (or ZESARUX_PATH) and starts it with the ZRCP remote protocol enabled.
Inputs: no named parameters.
list_breakpointsB
List breakpoints (ZRCP get-breakpoints). Optionally page from a starting index.
Inputs: index, items.
load_fileA
Load a file into the emulator. By default uses ZEsarUX smartload, which auto-detects the file type and runs it. Use file_type to force a specific loader.
Inputs: filename (required), file_type.
load_snapshotB
Load emulator state from a snapshot file (ZRCP snapshot-load).
Inputs: filename (required).
mmc_reloadB
Reload the configured MMC file (ZRCP mmc-reload). Takes no arguments.
Inputs: no named parameters.
peekC
Read bytes from emulated memory (ZRCP read-memory)
Inputs: address (required), length, memory_zone, format.
pokeB
Write bytes to emulated memory (ZRCP write-memory, space-separated bytes)
Inputs: address (required), value (required), memory_zone.
read_portA
Read a byte from an I/O port. ZEsarUX has no read-port command, so this evaluates IN(port) and returns the integer value.
Inputs: port (required).
reset_machineA
Reset the emulated machine. Soft reset sends ZRCP "reset-cpu"; hard reset sends "hard-reset-cpu".
Inputs: hard_reset.
save_screenA
Save the current emulator screen to a file on the ZEsarUX host (ZRCP save-screen). Format is inferred from the file extension; only scr, bmp and pbm are supported.
Inputs: filename (required), format.
save_snapshotA
Save the emulator state to a snapshot file (ZRCP snapshot-save). The format is determined by the file extension (e.g. .zsf, .sna, .z80, .sp) — there is no separate format argument.
Inputs: filename (required).
send_keyA
Send a single key to the emulator. Printable keys (and ENTER/SPACE/TAB) are delivered via send-keys-ascii. press/release require a numeric util_teclas key_code (send-keys-event).
Inputs: key (required), action, key_code, time.
send_keysB
Type a string into the emulator via send-keys-ascii (one ASCII code per character; useful for BASIC commands like LOAD "").
Inputs: keys (required), delay.
set_breakpointA
Set a breakpoint in a numbered slot (ZRCP set-breakpoint). A breakpoint is an EXPRESSION condition that fires when non-zero. Provide a raw "condition" (e.g. "PC=8000", "MWA=16384", "A=0 and BC<33"), or provide "type"+"address" to have it compiled. Memory read/write use set-membreakpoint; execute uses PC=addr; port read/write use PRA/PWA. Empty condition disables the slot.
Inputs: index (required), condition, address, type, +3 more.
set_machineA
Set the emulated machine type in ZEsarUX (ZRCP "set-machine "). Use a real ZEsarUX machine identifier.
Inputs: machine (required).
set_registerA
Set a CPU register value. Maps to ZRCP "set-register REG=VALUEH" (e.g. set-register DE=3344H).
Inputs: register (required), value (required).
snapshot_inramA
Access ZEsarUX in-RAM ("Time Machine") snapshots — an automatic ring buffer. Supports "load" (snapshot-inram-load) and "get_index" (snapshot-inram-get-index); position 0 is the oldest. Saving/listing/deleting are NOT supported over ZRCP.
Inputs: action (required), index (required).
tape_controlA
Insert a real tape into the emulator. NOTE: ZEsarUX ZRCP only supports inserting a real tape (realtape-open); transport actions (play/stop/rewind/forward) are NOT available over ZRCP. For ordinary .tap/.tzx files, prefer load_file (smartload).
Inputs: action (required), filename.
write_portB
Write a byte to an I/O port (ZRCP write-port).
Inputs: port (required), value (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Most tools have clearly distinct purposes (e.g., assemble vs. disassemble, peek vs. hexdump). The only potential overlap is between get_screen and save_screen, which both save screen files but with different emphasis. Overall, an agent can reliably distinguish tools.
The vast majority of tool names follow a verb_noun pattern with underscores (e.g., clear_breakpoint, set_register, send_keys). A few names like snapshot_inram and tape_control deviate from this pattern, making the set slightly inconsistent.
With 34 tools, the count significantly exceeds the recommended range of 3–15. While the tools cover many emulator features, the number is high and could overwhelm an agent, leading to selection difficulties.
The tool set covers most major emulator operations: launch, memory, CPU, breakpoints, screen, snapshots, tape, AY player, and more. Minor gaps exist, such as missing tape transport commands and no direct OCR tool, but core workflows are well-supported.
Maintenance
Related MCP Connectors
Securely control paired computers with ReMCP.
Documentation for the Spektralwerk spectrometer SCPI API as a streamable HTTP MCP Server
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
Control Unreal Engine to browse assets, import content, and manage levels and sequences. Automate…
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables interaction with VICE emulators for Commodore systems through binary monitor protocol, supporting keyboard matrix injection and IEC observers for targets like C64, VIC-20, etc.GPL 2.0
- AlicenseBqualityCmaintenanceMCP server providing emulator control for a loopback-only DOSBox-X QMP server, with tools for keyboard input, memory reads, screenshots, and state snapshots to complement Ghidra's GDB TraceRMI debugging.132Apache 2.0
- AlicenseAqualityCmaintenanceEnables AI agents to run CP/M, MP/M, and DOS packages on Z80/x86 emulators, inspect byte-exact results and files, and debug the emulators themselves over the Model Context Protocol.7GPL 3.0
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to control an MSX emulator for debugging and reverse-engineering, including memory and code inspection, execution control, and saving annotations via MCP.-