VICE C64 Emulator MCP Server
Enables autonomous debugging of Commodore 64 programs through the VICE emulator, providing semantic interpretation of 6502 assembly code, memory operations, breakpoint management, VIC-II graphics state analysis, sprite debugging, and PETSCII screen text decoding.
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., "@VICE C64 Emulator MCP Server load my game.prg and set a breakpoint at the main loop"
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.
vice-mcp
A Model Context Protocol (MCP) server for autonomous C64 debugging via the VICE emulator.
What is this?
vice-mcp bridges AI agents to the VICE Commodore 64 emulator, enabling autonomous debugging of 6502 assembly programs. Unlike raw protocol wrappers, it provides a semantic layer that interprets C64-specific data structures and returns meaningful, actionable information.
Why this exists:
AI agents need more than hex dumps—they need interpreted data with context
Debugging C64 code requires understanding VIC-II banks, PETSCII encoding, sprite pointers, and memory layouts
Every response includes hints suggesting next steps and related tools
Key differentiators:
Semantic output:
readScreenreturns text, not screen codes.readVicStateexplains graphics modes, not register bits.Actionable hints: Every response suggests what to do next
Cross-references: Tools point to related tools for common workflows
Agent-friendly errors: Clear error codes and recovery suggestions
Related MCP server: pet-tools-mcp
Prerequisites
Node.js 18 or later
VICE emulator with binary monitor enabled
Starting VICE with Binary Monitor
# x64sc is the accurate C64 emulator (recommended)
x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502
# Or with x64 (faster, less accurate)
x64 -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502The binary monitor listens on port 6502 by default.
Installation
From npm (when published)
npx @simen/vice-mcpFrom GitHub
npx github:simen/vice-mcpLocal Development
git clone https://github.com/simen/vice-mcp.git
cd vice-mcp
npm install
npm run build
npm startClaude Code Installation
The quickest way to get started with Claude Code:
1. Start VICE with binary monitor:
x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:65022. Add the MCP server:
claude mcp add vice-mcp -- npx github:simen/vice-mcp3. Restart Claude Code to load the new MCP server.
That's it! You can now ask Claude Code to debug your C64 programs.
Manual Configuration
Alternatively, add to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"vice-mcp": {
"command": "npx",
"args": ["github:simen/vice-mcp"]
}
}
}Configuration
Add to your MCP client configuration (e.g., Claude Desktop, Cursor, or custom agent):
{
"mcpServers": {
"vice": {
"command": "npx",
"args": ["@simen/vice-mcp"]
}
}
}Or for local development:
{
"mcpServers": {
"vice": {
"command": "node",
"args": ["/path/to/vice-mcp/dist/index.js"]
}
}
}Tool Reference
Connection & Status
Tool | Description |
| Connect to VICE (default: 127.0.0.1:6502) |
| Disconnect from VICE |
| Get connection state and emulation status |
Memory Operations
Tool | Description |
| Read raw bytes with hex dump and ASCII |
| Write bytes to memory |
CPU & Execution
Tool | Description |
| Get A, X, Y, SP, PC, and flags (interpreted) |
| Single-step execution (with step-over option) |
| Resume execution |
| Soft or hard reset |
| Run until specific address (temporary breakpoint) |
| Disassemble 6502 code with KERNAL labels |
Breakpoints & Watchpoints
Tool | Description |
| Set execution breakpoint |
| Remove breakpoint or watchpoint |
| List all breakpoints |
| Enable/disable breakpoint |
| Set memory read/write watchpoint |
| List all watchpoints |
Semantic Layer (Interpreted C64 Data)
Tool | Description |
| Get screen as text (PETSCII decoded) with summary mode |
| Get color RAM with color names and usage stats |
| Full VIC-II state: graphics mode, colors, banks, sprites |
| All 8 sprites: position, visibility, colors, pointers |
Visual Feedback
Tool | Description |
| Capture display buffer with palette |
| ASCII art rendering of display |
State Management
Tool | Description |
| Save complete machine state to file |
| Load machine state from file |
| Load and optionally run PRG/D64/T64 files |
Example Usage
Basic Debugging Session
1. connect() → Establish connection
2. loadProgram("game.prg") → Load the program
3. setBreakpoint(0x0810) → Break at main loop
4. continue() → Run until breakpoint
5. getRegisters() → Check CPU state
6. readScreen() → See what's on screen
7. step(count: 5) → Execute 5 instructions
8. disassemble() → See code at current PCDebugging Sprite Issues
1. readVicState() → Check sprite enable bits
2. readSprites(enabledOnly: true) → Get enabled sprite details
→ Response includes visibility check and position analysis
3. If sprite not visible, hint tells you why (off-screen, wrong bank, etc.)Memory Watchpoint Workflow
1. setWatchpoint(startAddress: 0x0400, type: "store")
→ Watch for writes to screen RAM
2. continue()
→ Execution stops when something writes to screen
3. getRegisters()
→ See PC to find the code that wrote
4. disassemble()
→ Understand what the code is doingState Checkpoint Pattern
1. saveSnapshot("before-test.vsf") → Save state
2. [Make changes, test things]
3. loadSnapshot("before-test.vsf") → Restore to known stateResponse Format
All responses include:
Structured data with
valueandhexrepresentations_metablock with connection statehintfield with contextual next steps
Example getRegisters response:
{
"a": { "value": 65, "hex": "$41" },
"x": { "value": 0, "hex": "$00" },
"y": { "value": 0, "hex": "$00" },
"sp": { "value": 243, "hex": "$f3", "stackTop": "$01f3" },
"pc": { "value": 2049, "hex": "$0801" },
"flags": {
"negative": false,
"overflow": false,
"zero": false,
"carry": false,
"string": "nv-bdizc"
},
"hint": "CPU state looks normal",
"_meta": {
"connected": true,
"running": false,
"host": "127.0.0.1",
"port": 6502
}
}Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ MCP Client (Agent) │
└─────────────────────────────────────────────────────────┘
│
│ MCP Protocol (stdio)
▼
┌─────────────────────────────────────────────────────────┐
│ src/index.ts │
│ (MCP Server) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Tool Handlers (24 tools) │ │
│ │ • Connection: connect, disconnect, status │ │
│ │ • Memory: readMemory, writeMemory │ │
│ │ • CPU: getRegisters, step, continue, reset │ │
│ │ • Breakpoints: set, delete, list, toggle │ │
│ │ • Watchpoints: set, list │ │
│ │ • Semantic: readScreen, readVicState, etc. │ │
│ │ • Visual: screenshot, renderScreen │ │
│ │ • State: saveSnapshot, loadSnapshot, loadPrg │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
│ Uses
▼
┌─────────────────────────────────────────────────────────┐
│ src/protocol/client.ts │
│ (ViceClient) │
│ • TCP socket connection to VICE │
│ • Binary protocol encoding/decoding │
│ • Request/response correlation │
│ • Checkpoint (breakpoint/watchpoint) tracking │
└─────────────────────────────────────────────────────────┘
│
│ TCP Socket
▼
┌─────────────────────────────────────────────────────────┐
│ VICE Binary Monitor │
│ (Port 6502) │
└─────────────────────────────────────────────────────────┘Key Files
File | Purpose |
| MCP server, tool definitions, semantic layer |
| VICE binary monitor client |
| Protocol constants and types |
| C64 utilities (PETSCII, colors, VIC banks) |
| 6502 disassembler with all addressing modes |
Design Principles
Semantic over raw: Return interpreted data, not just bytes
Hints everywhere: Every response suggests next actions
Cross-references: Tools reference related tools
Fail informatively: Errors explain what went wrong and how to fix it
Agent-first: Designed for autonomous operation, not human CLI use
Protocol Reference
vice-mcp implements the VICE Binary Monitor Protocol. Key commands used:
Code | Command | Purpose |
0x01 | MemoryGet | Read memory |
0x02 | MemorySet | Write memory |
0x12 | CheckpointSet | Create breakpoint/watchpoint |
0x13 | CheckpointDelete | Remove checkpoint |
0x15 | CheckpointToggle | Enable/disable checkpoint |
0x31 | RegistersGet | Read CPU registers |
0x41 | Dump | Save snapshot |
0x42 | Undump | Load snapshot |
0x81 | Continue | Resume execution |
0x82 | Step | Single-step |
0x84 | DisplayGet | Capture screen |
0x91 | PaletteGet | Get color palette |
0xdd | AutoStart | Load and run program |
License
MIT
Available Tools
26 toolsconnectA
Connect to a running VICE emulator instance via the binary monitor protocol.
VICE must be started with the binary monitor enabled: x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502
Default connection: 127.0.0.1:6502
Use this first before any debugging operations. Connection persists until disconnect() is called or VICE closes.
Related tools: status, disconnect
Inputs: host, port.
continueA
Resume C64 execution after a breakpoint or pause.
Starts the emulator running until the next breakpoint, manual stop, or error.
Related tools: step, status, setBreakpoint
Inputs: no named parameters.
deleteBreakpointA
Delete a breakpoint by its ID.
Use listBreakpoints to see current breakpoint IDs.
Related tools: setBreakpoint, listBreakpoints
Inputs: breakpointId (required).
disassembleA
Disassemble 6502 machine code at a memory address.
Returns human-readable assembly instructions with:
Address and raw bytes
Mnemonic and operand
Branch target addresses (for branch instructions)
Known KERNAL/BASIC labels
Options:
address: Start address (default: current PC)
count: Number of instructions (default: 10)
Related tools: readMemory, getRegisters, step
Inputs: address, count.
disconnectA
Disconnect from the VICE emulator instance.
Cleanly closes the connection. Safe to call even if not connected.
Related tools: connect, status
Inputs: no named parameters.
getRegistersA
Get current 6502/6510 CPU register state.
Returns all CPU registers with interpreted flags.
Registers:
A: Accumulator (arithmetic operations)
X, Y: Index registers (addressing, loops)
SP: Stack pointer ($100-$1FF range)
PC: Program counter (current instruction address)
Flags: N(egative), V(overflow), B(reak), D(ecimal), I(nterrupt), Z(ero), C(arry)
Use this to:
Check CPU state at breakpoints
Understand program flow
Debug crashes (check PC, SP)
Related tools: setRegister, step, continue, status
Inputs: no named parameters.
listBreakpointsA
List all active breakpoints.
Shows breakpoint IDs, addresses, and status for all breakpoints set in this session.
Note: This tracks breakpoints set through this MCP session. Breakpoints set through VICE's built-in monitor may not appear.
Related tools: setBreakpoint, deleteBreakpoint
Inputs: no named parameters.
listWatchpointsA
List all active memory watchpoints.
Shows watchpoint IDs, address ranges, type (load/store), and status.
Related tools: setWatchpoint, deleteBreakpoint, listBreakpoints
Inputs: no named parameters.
loadProgramB
Load and optionally run a program file.
Supports PRG, D64, T64, and other C64 file formats. For disk images, can specify which file to run.
Options:
run: If true (default), starts execution after loading
fileIndex: For disk images, which file to load (0 = first)
Related tools: reset, status, setBreakpoint
Inputs: filename (required), run, fileIndex.
loadSnapshotA
Load a previously saved machine state from a file.
Restores complete machine state including memory, registers, and peripheral states.
Warning: This completely replaces the current state!
Related tools: saveSnapshot
Inputs: filename (required).
readColorRamA
Read color RAM ($D800-$DBE7) and return color values with names.
Color RAM determines the foreground color of each character on screen.
Returns:
25x40 grid of color values (0-15) with names
Summary of colors used
Related tools: readScreen, readVicState
Inputs: summary.
readMemoryA
Read memory from the C64's address space.
Returns raw bytes plus hex and ASCII representations.
C64 memory map highlights:
$0000-$00FF: Zero page (fast access, common variables)
$0100-$01FF: Stack
$0400-$07FF: Default screen RAM (1000 bytes)
$D000-$D3FF: VIC-II registers (graphics)
$D400-$D7FF: SID registers (sound)
$D800-$DBFF: Color RAM
For screen content, consider using readScreen instead for interpreted output. For sprite info, use readSprites for semantic data.
Related tools: writeMemory, readScreen, readSprites, readVicState
Inputs: address (required), length.
readScreenA
Read the C64 screen memory and return it as interpreted text.
Converts PETSCII screen codes to readable ASCII. Returns 25 lines of 40 characters.
Use this instead of readMemory($0400) when you want to see what's displayed on screen.
Note: This reads from the current screen RAM location (may not be $0400 if the program moved it). In bitmap modes, the data won't represent text.
Options:
format: "full" (default) returns all 25 lines, "summary" returns only non-empty lines
includeRaw: Also return raw screen codes (default: false)
Related tools: readColorRam, readVicState, readMemory
Inputs: format, includeRaw.
readSpritesA
Read state of all 8 hardware sprites with interpreted values.
Returns for each sprite:
Position (X, Y) with visibility check
Color (with name)
Enable status
Multicolor mode
X/Y expansion (double size)
Priority (in front of / behind background)
Data pointer address
Use this to debug sprite issues like:
"Why is my sprite invisible?" → check enabled, position, pointer
"Wrong colors?" → check multicolor mode and color registers
"Wrong size?" → check expand flags
Options:
enabledOnly: Only return enabled sprites (default: false)
Related tools: readVicState, readMemory (for sprite data)
Inputs: enabledOnly.
readVicStateA
Read the full VIC-II state with interpreted values.
Returns all VIC-II registers with semantic meaning:
Border and background colors (with names)
Graphics mode (text, bitmap, multicolor, etc.)
Screen and character memory locations
Scroll values
Raster position
Sprite enable bits
This is the high-level view of the video chip. Use for understanding display configuration.
Related tools: readScreen, readSprites, readMemory (for $D000-$D02E)
Inputs: no named parameters.
renderScreenA
Render the current screen as ASCII art representation.
Creates a visual representation of the screen using ASCII characters to approximate the colors and content visible on the C64 display.
This is useful for quick visual debugging without image handling. For actual screen text, use readScreen instead.
Options:
width: Output width in characters (default: 80)
height: Output height in lines (default: 50)
charset: Character set to use for shading (default: " .:-=+*#%@")
Related tools: readScreen, screenshot, readVicState
Inputs: width, height, charset.
resetA
Reset the C64 machine.
Options:
hard: If true, performs hard reset (like power cycle). If false, soft reset (like reset button).
A soft reset preserves some memory contents, hard reset clears everything.
Related tools: connect, status
Inputs: hard.
runToA
Run execution until a specific address is reached.
Sets a temporary breakpoint at the target address and continues execution. The breakpoint is automatically deleted when hit.
Use for:
"Run until this function" → runTo(functionAddress)
"Skip to the end of this loop" → runTo(addressAfterLoop)
Related tools: continue, step, setBreakpoint
Inputs: address (required).
saveSnapshotA
Save the complete machine state to a file.
Creates a VICE snapshot file containing:
All memory (RAM, I/O states)
CPU registers
VIC-II, SID, CIA states
Disk drive state (if attached)
Use to:
Save state before risky debugging
Create restore points
Share exact machine state
Related tools: loadSnapshot
Inputs: filename (required).
screenshotA
Capture the current VICE display as image data.
Returns the raw display buffer with:
Pixel data (indexed 8-bit palette colors)
Display dimensions and visible area
Current palette RGB values
The data can be used to understand what's currently on screen visually. For text mode screens, readScreen provides a simpler text representation.
Options:
includePalette: Also return the color palette (default: true)
Related tools: readScreen, readVicState
Inputs: includePalette.
setBreakpointA
Set an execution breakpoint at a memory address.
When the PC reaches this address, execution stops. Use to:
Debug code at specific points
Catch when routines are called
Analyze code flow
Returns a breakpoint ID for later management.
Related tools: deleteBreakpoint, listBreakpoints, continue, step
Inputs: address (required), enabled, temporary.
setWatchpointA
Set a memory watchpoint to stop when memory is read or written.
Watchpoints are powerful for debugging:
"Why is this value changing?" → Use store watchpoint
"What's reading this address?" → Use load watchpoint
"Track all access to this region" → Use both
Range can be single address or address range (e.g., $D800-$DBFF for color RAM).
Related tools: deleteBreakpoint, listWatchpoints, continue
Inputs: startAddress (required), type (required), endAddress, enabled, +1 more.
statusA
Get current VICE connection and emulation state.
Returns connection status, whether emulation is running or paused, and host/port if connected.
Use this to:
Check if you're connected before running other commands
See if emulation is running or stopped (e.g., at a breakpoint)
Verify connection details
Related tools: connect, disconnect
Inputs: no named parameters.
stepA
Execute one or more instructions, then stop.
Single-stepping is essential for understanding code flow and debugging.
Options:
count: Number of instructions to execute (default: 1)
stepOver: If true, treat JSR as single instruction (don't step into subroutines)
After stepping, use getRegisters to see the new CPU state.
Related tools: getRegisters, continue, setBreakpoint, status
Inputs: count, stepOver.
toggleBreakpointA
Enable or disable a breakpoint without deleting it.
Use this to temporarily disable breakpoints while keeping their configuration.
Related tools: setBreakpoint, deleteBreakpoint, listBreakpoints
Inputs: breakpointId (required), enabled (required).
writeMemoryA
Write bytes to the C64's memory.
Directly modifies memory at the specified address. Changes take effect immediately.
Common uses:
Poke values for testing
Patch code at runtime
Modify screen/color RAM directly
Change VIC/SID registers
Be careful writing to ROM areas ($A000-$BFFF, $E000-$FFFF) - you may need to bank out ROM first.
Related tools: readMemory, fillMemory
Inputs: address (required), bytes (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 26 tools
Most tools have distinct purposes with clear boundaries, such as connect/disconnect for connection management, readMemory/readScreen for different memory views, and setBreakpoint/setWatchpoint for different debugging triggers. However, some tools like readScreen and renderScreen both provide screen representations, which could cause minor confusion about when to use each, though their descriptions clarify the differences.
Tool names follow a highly consistent verb_noun pattern throughout, such as connect, disconnect, getRegisters, listBreakpoints, readMemory, and writeMemory. All names use lowercase with clear, descriptive verbs and nouns, making the set predictable and easy to understand.
With 26 tools, the count is on the higher side for an emulator debugging server, which may feel heavy but is reasonable given the comprehensive coverage of debugging operations. It includes connection, execution control, memory access, breakpoints, screen rendering, and state management, though some tools could potentially be consolidated (e.g., readScreen and renderScreen).
The tool set provides complete coverage for C64 emulator debugging, including connection management, execution control (continue, step, runTo), breakpoint and watchpoint handling, memory and register access, screen and sprite inspection, state saving/loading, and reset functionality. There are no obvious gaps; all core debugging workflows are supported with logical tool relationships.
Maintenance
Related MCP Connectors
Shared debugging memory for AI coding agents
Sub-millisecond persistent memory, behavioral code search, and bug localization for AI agents.
AI-native programming language and toolchain for accountable, verifiable agent-driven development.
Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI-powered control and debugging of Commodore 64 programs via the VICE emulator, supporting memory operations, breakpoints, register access, and program loading.188 npmMIT
- AlicenseBqualityBmaintenanceEnables AI agents to code and debug Commodore PET software using the VICE emulator, with CLI and MCP tools for session control, screen reading, memory manipulation, and testing.441MIT
- 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
- AlicenseNot gradedqualityBmaintenanceLets AI clients control and program a Commodore 64, including running programs, reading/writing memory, rendering graphics, playing sound, and switching between C64 Ultimate hardware and VICE emulation.220 npm41GPL 2.0