MCP Hub
Back to servers

VICE C64 Emulator MCP Server

A specialized MCP server for autonomous Commodore 64 debugging that bridges AI agents to the VICE emulator via a semantic layer. It interprets C64-specific data structures like PETSCII text, VIC-II states, and 6502 registers to provide actionable insights for assembly debugging.

Tools
26
Updated
Dec 30, 2025

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: readScreen returns text, not screen codes. readVicState explains 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

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:6502

The binary monitor listens on port 6502 by default.

Installation

From npm (when published)

npx @simen/vice-mcp

From GitHub

npx github:simen/vice-mcp

Local Development

git clone https://github.com/simen/vice-mcp.git
cd vice-mcp
npm install
npm run build
npm start

Claude 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:6502

2. Add the MCP server:

claude mcp add vice-mcp -- npx github:simen/vice-mcp

3. 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

ToolDescription
connectConnect to VICE (default: 127.0.0.1:6502)
disconnectDisconnect from VICE
statusGet connection state and emulation status

Memory Operations

ToolDescription
readMemoryRead raw bytes with hex dump and ASCII
writeMemoryWrite bytes to memory

CPU & Execution

ToolDescription
getRegistersGet A, X, Y, SP, PC, and flags (interpreted)
stepSingle-step execution (with step-over option)
continueResume execution
resetSoft or hard reset
runToRun until specific address (temporary breakpoint)
disassembleDisassemble 6502 code with KERNAL labels

Breakpoints & Watchpoints

ToolDescription
setBreakpointSet execution breakpoint
deleteBreakpointRemove breakpoint or watchpoint
listBreakpointsList all breakpoints
toggleBreakpointEnable/disable breakpoint
setWatchpointSet memory read/write watchpoint
listWatchpointsList all watchpoints

Semantic Layer (Interpreted C64 Data)

ToolDescription
readScreenGet screen as text (PETSCII decoded) with summary mode
readColorRamGet color RAM with color names and usage stats
readVicStateFull VIC-II state: graphics mode, colors, banks, sprites
readSpritesAll 8 sprites: position, visibility, colors, pointers

Visual Feedback

ToolDescription
screenshotCapture display buffer with palette
renderScreenASCII art rendering of display

State Management

ToolDescription
saveSnapshotSave complete machine state to file
loadSnapshotLoad machine state from file
loadProgramLoad 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 PC

Debugging 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 doing

State Checkpoint Pattern

1. saveSnapshot("before-test.vsf")  → Save state
2. [Make changes, test things]
3. loadSnapshot("before-test.vsf")  → Restore to known state

Response Format

All responses include:

  • Structured data with value and hex representations
  • _meta block with connection state
  • hint field 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

FilePurpose
src/index.tsMCP server, tool definitions, semantic layer
src/protocol/client.tsVICE binary monitor client
src/protocol/types.tsProtocol constants and types
src/utils/c64.tsC64 utilities (PETSCII, colors, VIC banks)
src/utils/disasm.ts6502 disassembler with all addressing modes

Design Principles

  1. Semantic over raw: Return interpreted data, not just bytes
  2. Hints everywhere: Every response suggests next actions
  3. Cross-references: Tools reference related tools
  4. Fail informatively: Errors explain what went wrong and how to fix it
  5. Agent-first: Designed for autonomous operation, not human CLI use

Protocol Reference

vice-mcp implements the VICE Binary Monitor Protocol. Key commands used:

CodeCommandPurpose
0x01MemoryGetRead memory
0x02MemorySetWrite memory
0x12CheckpointSetCreate breakpoint/watchpoint
0x13CheckpointDeleteRemove checkpoint
0x15CheckpointToggleEnable/disable checkpoint
0x31RegistersGetRead CPU registers
0x41DumpSave snapshot
0x42UndumpLoad snapshot
0x81ContinueResume execution
0x82StepSingle-step
0x84DisplayGetCapture screen
0x91PaletteGetGet color palette
0xddAutoStartLoad and run program

License

MIT

Reviews

No reviews yet

Sign in to write a review