VICE MCP

MCP server embedded in the VICE Commodore 64/128/VIC-20/PET emulator, giving AI assistants direct access to read/write memory, set breakpoints, inspect VIC-II/SID/CIA registers, and debug 6502 assembly in real time with 63 tools.

Documentation

VICE MCP - AI Meets the Commodore 64

VICE MCP is a Walker Heavy Industries project.

An MCP server embedded directly inside VICE, giving AI agents and modern tools full programmatic control over the world's most iconic 8-bit computer.

Load a disk image. Set breakpoints. Inspect sprites. Read SID registers. Type on the keyboard. Take screenshots. Step through 6502 code. All through a clean JSON-RPC API that any MCP client can speak.

This is VICE — the legendary Commodore emulator — with a Model Context Protocol server built into its core. Not bolted on. Not a wrapper. ~17,000 lines of C woven into the emulator itself.

What Can You Do With This?

For AI Agents

Point any MCP-compatible client - Claude Desktop, Cursor, your own agent - at http://127.0.0.1:6510/mcp and you have a fully controllable Commodore 64. Your agent can:

  • Load and run software — autostart PRGs and disk images
  • Debug 6502 code — breakpoints, watchpoints, conditional breaks, single-stepping
  • Inspect everything — CPU registers, memory banks, VIC-II graphics, SID audio, CIA timers
  • See what's on screen — take screenshots, read sprite bitmaps as ASCII art
  • Interact like a human — type text, press keys, move joysticks
  • Measure performance — cycle-accurate stopwatch, execution tracing, interrupt logging
  • Save and restore state — full snapshot management with metadata

For C64 Developers

If you write code for the Commodore 64, this gives you a modern debugging workflow without leaving your editor:

  • Set breakpoints from your IDE while your program runs
  • Load KickAssembler or VICE symbol files and debug by label name
  • Search memory for byte patterns with wildcard support
  • Compare memory regions against saved snapshots to find what changed
  • Trace execution with PC-range filtering to focus on your code
  • Log interrupts to understand IRQ/NMI timing
  • Group breakpoints and toggle them as a set

For Researchers & Educators

  • Automate ROM analysis and reverse engineering
  • Build interactive tutorials that control a live C64
  • Capture screen states for documentation
  • Replay and analyze historical software

63 Tools Across 14 Categories

Every tool follows MCP conventions with full JSON Schema validation, meaningful errors, and consistent parameter naming.

CategoryToolsWhat They Do
Executionvice.execution.run vice.execution.pause vice.execution.step vice.run_untilControl the CPU — resume, halt, single-step, run to address or cycle count
Registersvice.registers.get vice.registers.setRead/write all 6502 registers (A, X, Y, SP, PC, status flags)
Memoryvice.memory.read vice.memory.write vice.memory.banks vice.memory.search vice.memory.fill vice.memory.compareFull memory access with bank selection, pattern search with wildcards
Checkpointsvice.checkpoint.add vice.checkpoint.delete vice.checkpoint.list vice.checkpoint.toggle vice.checkpoint.set_condition vice.checkpoint.set_ignore_count vice.checkpoint.group.* vice.checkpoint.set_auto_snapshot vice.checkpoint.clear_auto_snapshotBreakpoints, watchpoints, tracepoints — with conditions, groups, and auto-snapshots
Spritesvice.sprite.get vice.sprite.set vice.sprite.inspectRead/write sprite state, ASCII art bitmap visualization
VIC-IIvice.vicii.get_state vice.vicii.set_stateFull access to the C64's video chip — raster, colors, scroll, bank
SIDvice.sid.get_state vice.sid.set_stateThe legendary sound chip — voices, filters, ADSR, waveforms
CIAvice.cia.get_state vice.cia.set_stateTimer and I/O chip state — both CIA1 and CIA2
Diskvice.disk.attach vice.disk.detach vice.disk.list vice.disk.read_sectorMount D64/D71/D81 images, browse directories, read raw sectors
Machinevice.machine.reset vice.machine.config.get vice.machine.config.set vice.autostartHard/soft reset, resource control (warp, speed, model), program loading
Displayvice.display.screenshot vice.display.get_dimensionsScreen capture to file or base64, display geometry
Inputvice.keyboard.type vice.keyboard.key_press vice.keyboard.key_release vice.keyboard.restore vice.keyboard.matrix vice.joystick.setKeyboard and joystick — text typing, individual keys, direct matrix, RESTORE/NMI
Debugvice.disassemble vice.symbols.load vice.symbols.lookup vice.watch.add vice.backtrace vice.cycles.stopwatchDisassembly, symbol files, call stack, cycle-accurate timing
Snapshotsvice.snapshot.save vice.snapshot.load vice.snapshot.listFull emulator state save/restore with JSON metadata
Tracingvice.trace.start vice.trace.stop vice.interrupt.log.start vice.interrupt.log.stop vice.interrupt.log.readExecution recording with PC filtering, IRQ/NMI/BRK event capture

Architecture

This isn't a sidecar process or a screen-scraper. The MCP server is compiled directly into VICE as a first-class subsystem — across every machine VICE emulates.

Supported Machines

MachineCPUNotable Hardware
C64 / C64 SC6510VIC-II, SID, 2×CIA, Sprites
C1288502/Z80VIC-II, VDC 80-col, SID, 2×CIA
SCPU6465816SuperCPU accelerator
C64 DTV6510 (extended)DTV-specific registers
VIC-206502VIC-I video, expansion memory
Plus/4 & C167501/8501TED video+audio chip
PET6502CRTC video, PIA/VIA I/O
CBM-II6509CRTC, MOS 6526 CIA

The MCP server adapts to the running machine automatically. When an AI agent calls vice.machine.config.get, it receives the actual hardware configuration — which chips are present, what memory banks exist, valid address ranges, and available resources. An agent debugging a VIC-20 cartridge gets VIC-I registers; the same agent debugging a C128 program gets VIC-II and the VDC 80-column display.

┌─────────────────────────────────────────────────┐
│                   VICE Emulator                  │
│                                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │   CPU    │  │  Video   │  │    Audio     │  │
│  │ (varies) │  │ (varies) │  │   (varies)   │  │
│  └────┬─────┘  └────┬─────┘  └──────┬───────┘  │
│       │              │               │           │
│       └──────────┬───┴───────────────┘           │
│                  │                                │
│         ┌────────┴────────┐                      │
│         │  MCP Server     │                      │
│         │  (libmcp.a)     │                      │
│         │                 │                      │
│         │  JSON-RPC 2.0   │<---- POST /mcp -----│
│         │  libmicrohttpd  │---- GET /events 501>│
│         │  Trap Dispatch  │                      │
│         └─────────────────┘                      │
│                                                  │
└─────────────────────────────────────────────────┘
        127.0.0.1:6510 by default

Key design decisions:

  • Trap-based dispatch — HTTP requests are dispatched through VICE's trap mechanism, ensuring all tool logic executes on the emulator's main thread. No race conditions, no locking surprises.
  • Zero-copy access — Tools read directly from emulator internals. When you ask for VIC-II state, you get the actual register values, not a cached approximation.
  • Machine-aware responses — Tools report hardware capabilities, chip availability, and valid memory ranges for whatever machine is running. The agent always knows what it's working with.
  • Monitor integration — Works alongside VICE's built-in monitor. If the emulator is paused in the monitor, MCP requests execute directly without traps.
  • Reserved events endpointGET /events exists but currently returns 501 Not Implemented. Poll state through /mcp until event streaming lands.

Quick Start

Connect to VICE

Start any VICE machine with the MCP server enabled:

# C64 (cycle-exact)
x64sc -mcpserver

# C128
x128 -mcpserver

# VIC-20
xvic -mcpserver

# Listen on all network interfaces, port 7000
x64sc -mcpserver -mcpserverhost 0.0.0.0 -mcpserverport 7000

The MCP server starts on 127.0.0.1:6510 by default. MCP clients connect to:

http://127.0.0.1:6510/mcp

0.0.0.0 is a bind address, not a client address. It means "listen on every interface". A client on the same Mac still connects to 127.0.0.1; a client on another machine connects to the Mac's LAN IP address, for example http://192.168.1.42:6510/mcp.

Connection Recipes

Use caseStart VICE withClient URLAuth header
Same Mac, defaultx64sc -mcpserverhttp://127.0.0.1:6510/mcpNone
Same Mac, custom portx64sc -mcpserver -mcpserverport 7000http://127.0.0.1:7000/mcpNone
LAN access, trusted networkx64sc -mcpserver -mcpserverhost 0.0.0.0http://<mac-lan-ip>:6510/mcpNone
LAN access with bearer tokenx64sc -mcpserver -mcpserverhost 0.0.0.0 -mcpservertoken secrethttp://<mac-lan-ip>:6510/mcpAuthorization: Bearer secret
Browser app with CORSx64sc -mcpserver -mcpservercorsorigin http://localhost:3000 -mcpservertoken secrethttp://127.0.0.1:6510/mcpAuthorization: Bearer secret

Token rules are intentionally simple:

  • No token configured: non-browser MCP clients can connect without an Authorization header.
  • Token configured: every MCP request must include Authorization: Bearer <token>.
  • CORS configured: a token is required. Wildcard CORS (*) is rejected.
  • Binding to 0.0.0.0 without a token is allowed for backwards compatibility, but VICE logs a warning because remote clients can control the emulator.

Talk to It

All HTTP requests go to /mcp, must use Content-Type: application/json, and should send Accept: application/json.

# Direct JSON-RPC call
curl -sS http://127.0.0.1:6510/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "vice.ping"
}'

# Standard MCP tools/call form, used by Claude Code and other MCP clients
curl -sS http://127.0.0.1:6510/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data '{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": { "name": "vice_ping", "arguments": {} }
}'

# Read the BASIC ROM entry point
curl -sS http://127.0.0.1:6510/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data '{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "vice_memory_read",
    "arguments": { "address": "0xA000", "size": 16, "encoding": "hex" }
  }
}'

When a token is configured, add the bearer header to every request:

curl -sS http://127.0.0.1:6510/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer secret' \
  --data '{"jsonrpc":"2.0","id":1,"method":"vice.ping"}'

Use with Claude Desktop

Add this to your Claude Desktop MCP config:

{
  "mcpServers": {
    "vice": {
      "url": "http://127.0.0.1:6510/mcp"
    }
  }
}

Then just talk to it: "Load the game on drive 8 and show me what's on screen."

If VICE was started with -mcpservertoken, the client must send Authorization: Bearer <token> on every request. If your MCP client cannot configure HTTP headers, do not use a token for local-only 127.0.0.1 sessions.

Building from Source

Prerequisites

PlatformInstall
Debian/Ubuntuapt install build-essential autoconf automake pkg-config libmicrohttpd-dev libgtk-3-dev xa65 flex byacc
macOSbrew install autoconf automake pkg-config libmicrohttpd gtk+3 xa lame
Windows (MSYS2)pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-libmicrohttpd mingw-w64-x86_64-gtk3 autoconf automake pkg-config

Build

cd vice
./autogen.sh
mkdir build && cd build
../configure --enable-mcp-server --enable-gtk3ui
make -j$(nproc)

Verify

# MCP flags should appear in help output
src/x64sc -help | grep mcp

# Expected:
# -mcpserver          Enable MCP server
# -mcpserverport <port>  Set MCP server port (default: 6510)
# -mcpserverhost <host>  Set MCP server host (default: 127.0.0.1)

Pre-built Binaries

Pre-built binaries are available on the Releases page.

PlatformGUIHeadlessNotes
Linux x86_64YesYesGTK3 UI
macOS arm64YesYesGTK3 UI (Apple Silicon)
Windows x86_64NoYesHeadless only — cross-compiled via MinGW-w64

Windows does not include a GUI build. GTK3 cross-compilation for Windows is not supported by VICE's build system. If you need a Windows GUI, build from source natively using MSYS2.

Python Client

A resilient Python client is included with retry logic, connection pooling, and a convenience method for every tool:

from tools.resilience.vice_mcp_resilient import ViceMCPClient

with ViceMCPClient("http://127.0.0.1:6510") as vice:
    # Load a program
    vice.autostart("/path/to/game.prg")

    # Set a breakpoint at the main loop
    vice.checkpoint_add(start_address=0x0810, stop_address=0x0810)

    # Run until it hits
    vice.execution_run()

    # Read the screen
    regs = vice.registers_get()
    screenshot = vice.display_screenshot(format="base64")

    # Inspect a sprite
    art = vice.sprite_inspect(sprite_number=0)
    print(art)

Protocol Test Suite

167 tests across 25 test classes validate every tool, every parameter, and every error condition:

# Requires a running VICE instance with MCP enabled
pytest tools/tests/test_mcp_protocol.py -v

Real-World Usage

sim6502 — Unit Testing for 6502 Assembly

sim6502 is a unit testing framework for 6502/6510/65C02 assembly that uses VICE MCP as an execution backend. Write tests in a custom DSL, run them against a live VICE instance with cycle-accurate hardware:

suite "sprite collision" {
    load "game.prg"

    test "player hits enemy" {
        jsr setup_sprites
        poke $d015, #$03          ; enable sprites 0 and 1
        poke $d000, #$80          ; sprite 0 x = 128
        poke $d002, #$80          ; sprite 1 x = 128
        jsr main_loop
        assert $d01e & #$03 != 0  ; collision register set
    }
}

sim6502 connects over MCP to load programs, set breakpoints, read registers, compare memory, and snapshot/restore state between tests — bringing modern CI/CD practices to retro computing development.

AI Agent Workflows

Any MCP-compatible client can drive VICE directly:

  • Claude Desktop / Cursor — "Load this disk image, find the main loop, and explain what the IRQ handler does"
  • Custom agents — Automated ROM analysis, regression testing, screenshot capture
  • Research tools — Systematic exploration of historical software behavior

Security

The MCP server is localhost-only by default (127.0.0.1). With the default settings, only programs on the same machine can connect.

It has no TLS. It has optional bearer-token authentication. It is designed for local development first, and network exposure should be deliberate.

If you need remote access, put it behind a reverse proxy with proper auth:

nginx/caddy -> auth -> https -> 127.0.0.1:6510

Binding to 0.0.0.0 is supported via -mcpserverhost. That makes VICE listen on every network interface. It does not mean clients connect to 0.0.0.0; remote clients connect to the Mac/Linux/Windows host's real IP address.

Use this checklist for remote sessions:

  • Start VICE with -mcpserverhost 0.0.0.0.
  • Prefer adding -mcpservertoken <token> unless the network is already trusted.
  • Configure the client URL as http://<host-ip>:6510/mcp.
  • If a token is configured, configure the client to send Authorization: Bearer <token>.
  • For browser-based clients, also configure one exact -mcpservercorsorigin <origin> and a token. CORS without a token is rejected.

Relationship to Upstream VICE

This is a fork of the VICE SVN mirror. The MCP server is implemented as a self-contained subsystem in src/mcp/ — it touches VICE internals through well-defined interfaces but doesn't modify core emulation logic.

The main branch tracks upstream VICE. The mcp-server branch contains all MCP additions.

The goal is to contribute this work back to the VICE project. The implementation is structured to export cleanly as unified diffs for SVN submission.

Tool Reference

Click to expand full reference for all 64 tools

Execution Control

vice.ping

Check if VICE is responding. No parameters.

vice.execution.run

Resume execution. No parameters.

vice.execution.pause

Pause execution. No parameters.

vice.execution.step

Step one or more instructions.

ParameterTypeRequiredDescription
countnumberNumber of instructions to step
stepOverbooleanStep over subroutines

vice.run_until

Run until address or for N cycles with timeout.

ParameterTypeRequiredDescription
addressstringTarget address (hex, decimal, or symbol name)
cyclesnumberMax cycles to run

Registers

vice.registers.get

Get all CPU registers (A, X, Y, SP, PC, status flags). No parameters.

vice.registers.set

Set a CPU register value.

ParameterTypeRequiredDescription
registerstringyesRegister name: PC A X Y SP N V B D I Z C
valuenumberyesValue to set

Memory

vice.memory.read

Read a memory range with optional bank selection.

ParameterTypeRequiredDescription
addressstringyesAddress: number, hex ($1000), or symbol name
sizenumberyesBytes to read (1-65535)
bankstringMemory bank name (use vice.memory.banks to list)

vice.memory.write

Write bytes to memory.

ParameterTypeRequiredDescription
addressstringyesAddress: number, hex ($1000), or symbol name
datanumber[]yesBytes to write (0-255 each)

vice.memory.banks

List available memory banks for the current machine. No parameters.

vice.memory.search

Search for byte patterns with optional wildcard mask.

ParameterTypeRequiredDescription
startstringyesStart address
endstringyesEnd address
patternnumber[]yesByte pattern, e.g. [0x4C, 0x00, 0xA0]
masknumber[]Per-byte mask: 0xFF=exact, 0x00=wildcard
max_resultsnumberMax matches (default: 100, max: 10000)

vice.memory.fill

Fill a memory range with a repeating byte pattern.

ParameterTypeRequiredDescription
startstringyesStart address
endstringyesEnd address (inclusive)
patternnumber[]yesByte pattern to repeat

vice.memory.compare

Compare two memory ranges or compare against a snapshot.

ParameterTypeRequiredDescription
modestringyesranges or snapshot
range1_startstringrangesStart of first range
range1_endstringrangesEnd of first range
range2_startstringrangesStart of second range
snapshot_namestringsnapshotSnapshot to compare against
startstringsnapshotStart address to compare
endstringsnapshotEnd address to compare
max_differencesnumberMax diffs to return (default: 100)

Checkpoints & Breakpoints

vice.checkpoint.add

Add a checkpoint (breakpoint, watchpoint, or tracepoint).

ParameterTypeRequiredDescription
startstringyesStart address
endstringEnd address (default = start)
stopbooleanStop on hit (default: true)
loadbooleanBreak on memory read (default: false)
storebooleanBreak on memory write (default: false)
execbooleanBreak on execution (default: true)

vice.checkpoint.delete

Delete a checkpoint.

ParameterTypeRequiredDescription
checkpoint_numnumberyesCheckpoint number

vice.checkpoint.list

List all checkpoints. No parameters.

vice.checkpoint.toggle

Enable or disable a checkpoint.

ParameterTypeRequiredDescription
checkpoint_numnumberyesCheckpoint number
enabledbooleanyesEnable or disable

vice.checkpoint.set_condition

Set a condition expression on a checkpoint.

ParameterTypeRequiredDescription
checkpoint_numnumberyesCheckpoint number
conditionstringyesExpression, e.g. A == $42

vice.checkpoint.set_ignore_count

Set how many hits to ignore before stopping.

ParameterTypeRequiredDescription
checkpoint_numnumberyesCheckpoint number
countnumberyesHits to ignore

vice.checkpoint.group.create

Create a named checkpoint group.

ParameterTypeRequiredDescription
namestringyesGroup name
checkpoint_idsnumber[]Initial checkpoint IDs

vice.checkpoint.group.add

Add checkpoints to an existing group.

ParameterTypeRequiredDescription
groupstringyesGroup name
checkpoint_idsnumber[]yesCheckpoint IDs to add

vice.checkpoint.group.toggle

Enable or disable all checkpoints in a group.

ParameterTypeRequiredDescription
groupstringyesGroup name
enabledbooleanyesEnable or disable all

vice.checkpoint.group.list

List all checkpoint groups. No parameters.

vice.checkpoint.set_auto_snapshot

Auto-save a snapshot when a checkpoint is hit.

ParameterTypeRequiredDescription
checkpoint_idnumberyesCheckpoint ID
snapshot_prefixstringyesFilename prefix (e.g. crash_repro)
max_snapshotsnumberRing buffer size (default: 10)
include_disksbooleanInclude disk state (default: false)

vice.checkpoint.clear_auto_snapshot

Remove auto-snapshot from a checkpoint.

ParameterTypeRequiredDescription
checkpoint_idnumberyesCheckpoint ID

Sprites (C64/C128/DTV)

vice.sprite.get

Get sprite state.

ParameterTypeRequiredDescription
spritenumberSprite number 0-7 (omit for all)

vice.sprite.set

Set sprite properties.

ParameterTypeRequiredDescription
spritenumberyesSprite number 0-7
xnumberX position 0-511
ynumberY position 0-255
enabledbooleanEnable sprite
multicolorbooleanMulticolor mode
expand_xbooleanDouble width
expand_ybooleanDouble height
priority_foregroundbooleanDraw over background
colornumberSprite color 0-15

vice.sprite.inspect

Visual ASCII art representation of a sprite's bitmap.

ParameterTypeRequiredDescription
sprite_numbernumberyesSprite number 0-7
formatstringascii (default), binary, or png_base64

Chip State

vice.vicii.get_state

Get VIC-II internal state. No parameters.

vice.vicii.set_state

Set VIC-II registers.

ParameterTypeRequiredDescription
registersobject[]Array of {offset, value} (offset 0x00-0x2E)

vice.sid.get_state

Get SID state (voices, filter, ADSR). No parameters.

vice.sid.set_state

Set SID registers.

ParameterTypeRequiredDescription
registersobject[]Array of {offset, value} (offset 0x00-0x1C)

vice.cia.get_state

Get CIA state (timers, ports).

ParameterTypeRequiredDescription
cianumberCIA number: 1 or 2 (omit for both)

vice.cia.set_state

Set CIA registers.

ParameterTypeRequiredDescription
cia1_registersobject[]Array of {offset, value} (offset 0x00-0x0F)
cia2_registersobject[]Array of {offset, value} (offset 0x00-0x0F)

Disk Management

vice.disk.attach

Attach a disk image to a drive.

ParameterTypeRequiredDescription
unitnumberyesDrive unit (8-11)
pathstringyesPath to disk image (.d64, .g64, etc.)

vice.disk.detach

Detach a disk image.

ParameterTypeRequiredDescription
unitnumberyesDrive unit (8-11)

vice.disk.list

List directory contents of an attached disk.

ParameterTypeRequiredDescription
unitnumberyesDrive unit (8-11)

vice.disk.read_sector

Read raw sector data.

ParameterTypeRequiredDescription
unitnumberyesDrive unit (8-11)
tracknumberyesTrack number (1-42 for D64)
sectornumberyesSector number

Machine Control

vice.autostart

Autostart a PRG or disk image.

ParameterTypeRequiredDescription
pathstringyesPath to .prg, .d64, .g64, etc.
programstringProgram name to load from disk
runbooleanRun after loading (default: true)
indexnumberProgram index on disk, 0-based

vice.machine.reset

Reset the machine.

ParameterTypeRequiredDescription
modestringsoft (default) or hard (power cycle)
run_afterbooleanResume after reset (default: true)

vice.machine.config.get

Get machine configuration — chips, memory map, resources. No parameters.

vice.machine.config.set

Set machine resources.

ParameterTypeRequiredDescription
resourcesobjectyesResource name/value pairs, e.g. {"WarpMode": 1}

Display

vice.display.screenshot

Capture the screen.

ParameterTypeRequiredDescription
pathstringFile path to save
formatstringPNG (default) or BMP
return_base64booleanReturn as base64 data URI

vice.display.get_dimensions

Get display dimensions. No parameters.


Input

vice.keyboard.type

Type text with automatic PETSCII conversion.

ParameterTypeRequiredDescription
textstringyesText to type (\n for Return)
petscii_upperbooleanUppercase mapping (default: true)

vice.keyboard.key_press

Press a key.

ParameterTypeRequiredDescription
keystringyesKey name or single char
modifiersstring[]shift, control, alt, meta, etc.
hold_framesnumberHold duration in frames (1-300)
hold_msnumberHold duration in ms (1-5000)

vice.keyboard.key_release

Release a key.

ParameterTypeRequiredDescription
keystringyesKey name or single char
modifiersstring[]Modifiers to release

vice.keyboard.restore

Press/release the RESTORE key (triggers NMI).

ParameterTypeRequiredDescription
pressedbooleantrue=press, false=release (default: true)

vice.keyboard.matrix

Direct keyboard matrix control for games.

ParameterTypeRequiredDescription
keystringKey name: A-Z, 0-9, SPACE, RETURN, etc.
rownumberMatrix row 0-7 (alternative to key)
colnumberMatrix column 0-7 (alternative to key)
pressedbooleanKey state (default: true)
hold_framesnumberHold duration in frames
hold_msnumberHold duration in ms

vice.joystick.set

Set joystick state.

ParameterTypeRequiredDescription
portnumberPort 1 or 2 (default: 1)
directionstringup, down, left, right, center
firebooleanFire button (default: false)

Advanced Debugging

vice.disassemble

Disassemble memory to 6502 instructions.

ParameterTypeRequiredDescription
addressstringyesStart address
countnumberInstructions to disassemble (default: 10, max: 100)
show_symbolsbooleanShow symbol names (default: true)

vice.symbols.load

Load a symbol/label file.

ParameterTypeRequiredDescription
pathstringyesPath to .sym or .lbl file
formatstringauto, kickasm, vice, or simple

vice.symbols.lookup

Look up a symbol by name or address.

ParameterTypeRequiredDescription
namestringSymbol name (returns address)
addressnumberAddress (returns symbol name)

vice.watch.add

Add a memory watchpoint.

ParameterTypeRequiredDescription
addressstringyesAddress to watch
sizenumberBytes to watch (default: 1)
typestringread, write, or both (default: write)
conditionstringCondition, e.g. A == $42

vice.backtrace

Show call stack from JSR return addresses.

ParameterTypeRequiredDescription
depthnumberMax frames (default: 16, max: 64)

vice.cycles.stopwatch

Measure elapsed CPU cycles.

ParameterTypeRequiredDescription
actionstringyesreset, read, or reset_and_read

Snapshots

vice.snapshot.save

Save complete emulator state.

ParameterTypeRequiredDescription
namestringyesSnapshot name (alphanumeric, _, -)
descriptionstringWhat this snapshot captures
include_romsbooleanInclude ROMs (default: false)
include_disksbooleanInclude disk state (default: false)

vice.snapshot.load

Restore emulator state from a snapshot.

ParameterTypeRequiredDescription
namestringyesSnapshot name

vice.snapshot.list

List all snapshots with metadata. No parameters.


Execution Tracing

vice.trace.start

Start recording executed instructions.

ParameterTypeRequiredDescription
output_filestringyesPath to output file
pc_filter_startnumberFilter start address (default: 0)
pc_filter_endnumberFilter end address (default: 65535)
max_instructionsnumberMax to record (default: 10000)
include_registersbooleanInclude register state (default: false)

vice.trace.stop

Stop tracing and get statistics.

ParameterTypeRequiredDescription
trace_idstringyesTrace ID from vice.trace.start

Interrupt Logging

vice.interrupt.log.start

Start logging IRQ, NMI, and BRK events.

ParameterTypeRequiredDescription
typesstring[]Filter: irq, nmi, brk (default: all)
max_entriesnumberMax entries (default: 1000, max: 10000)

vice.interrupt.log.stop

Stop logging and retrieve all entries.

ParameterTypeRequiredDescription
log_idstringyesLog ID from vice.interrupt.log.start

vice.interrupt.log.read

Read entries without stopping the log.

ParameterTypeRequiredDescription
log_idstringyesLog ID
since_indexnumberReturn entries from this index onwards

Project Status

This is active, working software. The MCP server compiles and runs on Linux, macOS, and Windows. All 64 tools are implemented and tested. CI produces binaries for all three platforms on every push.

What's solid:

  • Full tool suite — execution, memory, breakpoints, sprites, chip state, disk, input, debugging
  • Machine-aware responses across all VICE-emulated platforms
  • Python client with retry logic and full test coverage
  • Cross-platform builds: Linux x86_64 (GUI + headless), macOS arm64 (GUI + headless), Windows x86_64 (headless)
  • Automated CI/CD pipeline with binary releases

What's in progress:

  • Event streaming. GET /events is reserved but returns 501 Not Implemented today.
  • Execution tracing and interrupt logging hooks into VICE CPU core

Contributing

"Cross over, children. All are welcome. All welcome." — Tangina Barrons, speaking to contributors about this repo

This project bridges two communities that don't often overlap: retro computing and modern AI tooling. Contributions from either world (or both) are welcome.

Areas where help would be especially appreciated:

  • VICE internals — Hooking execution tracing and interrupt logging into the CPU core
  • Event streaming transport — Adding real-time breakpoint and state-change notifications
  • Additional machine support — Testing and tuning tools for PET, CBM-II, Plus/4
  • Client libraries — TypeScript, Rust, Go clients
  • Documentation — Tutorials, example workflows, video demos
  • Testing — Running the protocol test suite against edge cases

The MCP server is entirely contained in vice/src/mcp/. Start there.

Versioning & releases

This repo follows the Walker Heavy Industries Build & Release Standard:

  • Conventional Commits are required. Versioning is automated with Cocogittofeat: bumps the minor, fix: the patch, and a !/BREAKING CHANGE bumps the major. Install the local commit hook once with cog install-hook --all (CI also validates commits).
  • On every push to main, CI runs cog bump --auto, which tags the next vX.Y.Z, updates CHANGELOG.md, and publishes a GitHub Release with the generated changelog notes.
  • The multi-OS build matrix (Linux/macOS/Windows) attaches its artifacts to that Release. The latest v tag / Release is the single source of truth for the version — there is no compute-version.sh and no vice-mcp-* tag prefix.

License

VICE is released under the GNU General Public License v2. The MCP server additions follow the same license.

Acknowledgments

  • The VICE Team for 30+ years of the best 8-bit emulator ever written
  • Anthropic for the Model Context Protocol specification
  • The Commodore 64 community — still going strong after four decades

Part of the suite

VICE MCP is part of the Walker Heavy Industries retro toolchain — modern tools for the retro 8- and 16-bit ecosystem.

  • House hub: https://whi.dev
  • Siblings: VICE Mac · VICE MCP · FamiForge · NESBasic · Novus · Miggy Draw · NovaVM