trackmcp
Back to directory

VICE emulator with an embedded MCP server for AI agents and automation

4 stars COthers Updated Aug 1, 2026

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
Execution`vice.execution.run` `vice.execution.pause` `vice.execution.step` `vice.run_until`Control the CPU — resume, halt, single-step, run to address or cycle count
Registers`vice.registers.get` `vice.registers.set`Read/write all 6502 registers (A, X, Y, SP, PC, status flags)
Memory`vice.memory.read` `vice.memory.write` `vice.memory.banks` `vice.memory.search` `vice.memory.fill` `vice.memory.compare`Full memory access with bank selection, pattern search with wildcards
Checkpoints`vice.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_snapshot`Breakpoints, watchpoints, tracepoints — with conditions, groups, and auto-snapshots
Sprites`vice.sprite.get` `vice.sprite.set` `vice.sprite.inspect`Read/write sprite state, ASCII art bitmap visualization
VIC-II`vice.vicii.get_state` `vice.vicii.set_state`Full access to the C64's video chip — raster, colors, scroll, bank
SID`vice.sid.get_state` `vice.sid.set_state`The legendary sound chip — voices, filters, ADSR, waveforms
CIA`vice.cia.get_state` `vice.cia.set_state`Timer and I/O chip state — both CIA1 and CIA2
Disk`vice.disk.attach` `vice.disk.detach` `vice.disk.list` `vice.disk.read_sector`Mount D64/D71/D81 images, browse directories, read raw sectors
Machine`vice.machine.reset` `vice.machine.config.get` `vice.machine.config.set` `vice.autostart`Hard/soft reset, resource control (warp, speed, model), program loading
Display`vice.display.screenshot` `vice.display.get_dimensions`Screen capture to file or base64, display geometry
Input`vice.keyboard.type` `vice.keyboard.key_press` `vice.keyboard.key_release` `vice.keyboard.restore` `vice.keyboard.matrix` `vice.joystick.set`Keyboard and joystick — text typing, individual keys, direct matrix, RESTORE/NMI
Debug`vice.disassemble` `vice.symbols.load` `vice.symbols.lookup` `vice.watch.add` `vice.backtrace` `vice.cycles.stopwatch`Disassembly, symbol files, call stack, cycle-accurate timing
Snapshots`vice.snapshot.save` `vice.snapshot.load` `vice.snapshot.list`Full emulator state save/restore with JSON metadata
Tracing`vice.trace.start` `vice.trace.stop` `vice.interrupt.log.start` `vice.interrupt.log.stop` `vice.interrupt.log.read`Execution 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.

code
┌─────────────────────────────────────────────────┐
│                   VICE Emulator                  │
│                                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │   CPU    │  │  Video   │  │    Audio     │  │
│  │ (varies) │  │ (varies) │  │   (varies)   │  │
│  └────┬─────┘  └────┬─────┘  └──────┬───────┘  │
│       │              │               │           │
│       └──────────┬───┴───────────────┘           │
│                  │                                │
│         ┌────────┴────────┐                      │
│         │  MCP Server     │                      │
│         │  (libmcp.a)     │                      │
│         │                 │                      │
│         │  JSON-RPC 2.0   ││
│         │  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 endpoint — `GET /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:

bash
# 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:

text
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, default`x64sc -mcpserver``http://127.0.0.1:6510/mcp`None
Same Mac, custom port`x64sc -mcpserver -mcpserverport 7000``http://127.0.0.1:7000/mcp`None
LAN access, trusted network`x64sc -mcpserver -mcpserverhost 0.0.0.0``http://:6510/mcp`None
LAN access with bearer token`x64sc -mcpserver -mcpserverhost 0.0.0.0 -mcpservertoken secret``http://:6510/mcp``Authorization: Bearer secret`
Browser app with CORS`x64sc -mcpserver -mcpservercorsorigin http://localhost:3000 -mcpservertoken secret``http://127.0.0.1:6510/mcp``Authorization: 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 `.

  • 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`.

bash
# 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:

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

json
{
  "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 ` 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/Ubuntu`apt install build-essential autoconf automake pkg-config libmicrohttpd-dev libgtk-3-dev xa65 flex byacc`
macOS`brew 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

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

Verify

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

# Expected:
# -mcpserver          Enable MCP server
# -mcpserverport   Set MCP server port (default: 6510)
# -mcpserverhost   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:

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

bash
# 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:

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

code
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 ` unless the network is already trusted.
  • Configure the client URL as `http://:6510/mcp`.
  • If a token is configured, configure the client to send

`Authorization: Bearer `.

  • For browser-based clients, also configure one exact

`-mcpservercorsorigin ` 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
`count`numberNumber of instructions to step
`stepOver`booleanStep over subroutines

`vice.run_until`

Run until address or for N cycles with timeout.

ParameterTypeRequiredDescription
`address`stringTarget address (hex, decimal, or symbol name)
`cycles`numberMax 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
`register`stringyesRegister name: `PC` `A` `X` `Y` `SP` `N` `V` `B` `D` `I` `Z` `C`
`value`numberyesValue to set

Memory

`vice.memory.read`

Read a memory range with optional bank selection.

ParameterTypeRequiredDescription
`address`stringyesAddress: number, hex (`$1000`), or symbol name
`size`numberyesBytes to read (1-65535)
`bank`stringMemory bank name (use `vice.memory.banks` to list)

`vice.memory.write`

Write bytes to memory.

ParameterTypeRequiredDescription
`address`stringyesAddress: number, hex (`$1000`), or symbol name
`data`number[]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
`start`stringyesStart address
`end`stringyesEnd address
`pattern`number[]yesByte pattern, e.g. `[0x4C, 0x00, 0xA0]`
`mask`number[]Per-byte mask: `0xFF`=exact, `0x00`=wildcard
`max_results`numberMax matches (default: 100, max: 10000)

`vice.memory.fill`

Fill a memory range with a repeating byte pattern.

ParameterTypeRequiredDescription
`start`stringyesStart address
`end`stringyesEnd address (inclusive)
`pattern`number[]yesByte pattern to repeat

`vice.memory.compare`

Compare two memory ranges or compare against a snapshot.

ParameterTypeRequiredDescription
`mode`stringyes`ranges` or `snapshot`
`range1_start`stringrangesStart of first range
`range1_end`stringrangesEnd of first range
`range2_start`stringrangesStart of second range
`snapshot_name`stringsnapshotSnapshot to compare against
`start`stringsnapshotStart address to compare
`end`stringsnapshotEnd address to compare
`max_differences`numberMax diffs to return (default: 100)

Checkpoints & Breakpoints

`vice.checkpoint.add`

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

ParameterTypeRequiredDescription
`start`stringyesStart address
`end`stringEnd address (default = start)
`stop`booleanStop on hit (default: true)
`load`booleanBreak on memory read (default: false)
`store`booleanBreak on memory write (default: false)
`exec`booleanBreak on execution (default: true)

`vice.checkpoint.delete`

Delete a checkpoint.

ParameterTypeRequiredDescription
`checkpoint_num`numberyesCheckpoint number

`vice.checkpoint.list`

List all checkpoints. No parameters.

`vice.checkpoint.toggle`

Enable or disable a checkpoint.

ParameterTypeRequiredDescription
`checkpoint_num`numberyesCheckpoint number
`enabled`booleanyesEnable or disable

`vice.checkpoint.set_condition`

Set a condition expression on a checkpoint.

ParameterTypeRequiredDescription
`checkpoint_num`numberyesCheckpoint number
`condition`stringyesExpression, e.g. `A == $42`

`vice.checkpoint.set_ignore_count`

Set how many hits to ignore before stopping.

ParameterTypeRequiredDescription
`checkpoint_num`numberyesCheckpoint number
`count`numberyesHits to ignore

`vice.checkpoint.group.create`

Create a named checkpoint group.

ParameterTypeRequiredDescription
`name`stringyesGroup name
`checkpoint_ids`number[]Initial checkpoint IDs

`vice.checkpoint.group.add`

Add checkpoints to an existing group.

ParameterTypeRequiredDescription
`group`stringyesGroup name
`checkpoint_ids`number[]yesCheckpoint IDs to add

`vice.checkpoint.group.toggle`

Enable or disable all checkpoints in a group.

ParameterTypeRequiredDescription
`group`stringyesGroup name
`enabled`booleanyesEnable 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_id`numberyesCheckpoint ID
`snapshot_prefix`stringyesFilename prefix (e.g. `crash_repro`)
`max_snapshots`numberRing buffer size (default: 10)
`include_disks`booleanInclude disk state (default: false)

`vice.checkpoint.clear_auto_snapshot`

Remove auto-snapshot from a checkpoint.

ParameterTypeRequiredDescription
`checkpoint_id`numberyesCheckpoint ID

Sprites (C64/C128/DTV)

`vice.sprite.get`

Get sprite state.

ParameterTypeRequiredDescription
`sprite`numberSprite number 0-7 (omit for all)

`vice.sprite.set`

Set sprite properties.

ParameterTypeRequiredDescription
`sprite`numberyesSprite number 0-7
`x`numberX position 0-511
`y`numberY position 0-255
`enabled`booleanEnable sprite
`multicolor`booleanMulticolor mode
`expand_x`booleanDouble width
`expand_y`booleanDouble height
`priority_foreground`booleanDraw over background
`color`numberSprite color 0-15

`vice.sprite.inspect`

Visual ASCII art representation of a sprite's bitmap.

ParameterTypeRequiredDescription
`sprite_number`numberyesSprite number 0-7
`format`string`ascii` (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
`registers`object[]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
`registers`object[]Array of `{offset, value}` (offset 0x00-0x1C)

`vice.cia.get_state`

Get CIA state (timers, ports).

ParameterTypeRequiredDescription
`cia`numberCIA number: 1 or 2 (omit for both)

`vice.cia.set_state`

Set CIA registers.

ParameterTypeRequiredDescription
`cia1_registers`object[]Array of `{offset, value}` (offset 0x00-0x0F)
`cia2_registers`object[]Array of `{offset, value}` (offset 0x00-0x0F)

Disk Management

`vice.disk.attach`

Attach a disk image to a drive.

ParameterTypeRequiredDescription
`unit`numberyesDrive unit (8-11)
`path`stringyesPath to disk image (.d64, .g64, etc.)

`vice.disk.detach`

Detach a disk image.

ParameterTypeRequiredDescription
`unit`numberyesDrive unit (8-11)

`vice.disk.list`

List directory contents of an attached disk.

ParameterTypeRequiredDescription
`unit`numberyesDrive unit (8-11)

`vice.disk.read_sector`

Read raw sector data.

ParameterTypeRequiredDescription
`unit`numberyesDrive unit (8-11)
`track`numberyesTrack number (1-42 for D64)
`sector`numberyesSector number

Machine Control

`vice.autostart`

Autostart a PRG or disk image.

ParameterTypeRequiredDescription
`path`stringyesPath to .prg, .d64, .g64, etc.
`program`stringProgram name to load from disk
`run`booleanRun after loading (default: true)
`index`numberProgram index on disk, 0-based

`vice.machine.reset`

Reset the machine.

ParameterTypeRequiredDescription
`mode`string`soft` (default) or `hard` (power cycle)
`run_after`booleanResume 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
`resources`objectyesResource name/value pairs, e.g. `{"WarpMode": 1}`

Display

`vice.display.screenshot`

Capture the screen.

ParameterTypeRequiredDescription
`path`stringFile path to save
`format`string`PNG` (default) or `BMP`
`return_base64`booleanReturn as base64 data URI

`vice.display.get_dimensions`

Get display dimensions. No parameters.


Input

`vice.keyboard.type`

Type text with automatic PETSCII conversion.

ParameterTypeRequiredDescription
`text`stringyesText to type (`\n` for Return)
`petscii_upper`booleanUppercase mapping (default: true)

`vice.keyboard.key_press`

Press a key.

ParameterTypeRequiredDescription
`key`stringyesKey name or single char
`modifiers`string[]`shift`, `control`, `alt`, `meta`, etc.
`hold_frames`numberHold duration in frames (1-300)
`hold_ms`numberHold duration in ms (1-5000)

`vice.keyboard.key_release`

Release a key.

ParameterTypeRequiredDescription
`key`stringyesKey name or single char
`modifiers`string[]Modifiers to release

`vice.keyboard.restore`

Press/release the RESTORE key (triggers NMI).

ParameterTypeRequiredDescription
`pressed`booleantrue=press, false=release (default: true)

`vice.keyboard.matrix`

Direct keyboard matrix control for games.

ParameterTypeRequiredDescription
`key`stringKey name: `A`-`Z`, `0`-`9`, `SPACE`, `RETURN`, etc.
`row`numberMatrix row 0-7 (alternative to key)
`col`numberMatrix column 0-7 (alternative to key)
`pressed`booleanKey state (default: true)
`hold_frames`numberHold duration in frames
`hold_ms`numberHold duration in ms

`vice.joystick.set`

Set joystick state.

ParameterTypeRequiredDescription
`port`numberPort 1 or 2 (default: 1)
`direction`string`up`, `down`, `left`, `right`, `center`
`fire`booleanFire button (default: false)

Advanced Debugging

`vice.disassemble`

Disassemble memory to 6502 instructions.

ParameterTypeRequiredDescription
`address`stringyesStart address
`count`numberInstructions to disassemble (default: 10, max: 100)
`show_symbols`booleanShow symbol names (default: true)

`vice.symbols.load`

Load a symbol/label file.

ParameterTypeRequiredDescription
`path`stringyesPath to .sym or .lbl file
`format`string`auto`, `kickasm`, `vice`, or `simple`

`vice.symbols.lookup`

Look up a symbol by name or address.

ParameterTypeRequiredDescription
`name`stringSymbol name (returns address)
`address`numberAddress (returns symbol name)

`vice.watch.add`

Add a memory watchpoint.

ParameterTypeRequiredDescription
`address`stringyesAddress to watch
`size`numberBytes to watch (default: 1)
`type`string`read`, `write`, or `both` (default: `write`)
`condition`stringCondition, e.g. `A == $42`

`vice.backtrace`

Show call stack from JSR return addresses.

ParameterTypeRequiredDescription
`depth`numberMax frames (default: 16, max: 64)

`vice.cycles.stopwatch`

Measure elapsed CPU cycles.

ParameterTypeRequiredDescription
`action`stringyes`reset`, `read`, or `reset_and_read`

Snapshots

`vice.snapshot.save`

Save complete emulator state.

ParameterTypeRequiredDescription
`name`stringyesSnapshot name (alphanumeric, `_`, `-`)
`description`stringWhat this snapshot captures
`include_roms`booleanInclude ROMs (default: false)
`include_disks`booleanInclude disk state (default: false)

`vice.snapshot.load`

Restore emulator state from a snapshot.

ParameterTypeRequiredDescription
`name`stringyesSnapshot name

`vice.snapshot.list`

List all snapshots with metadata. No parameters.


Execution Tracing

`vice.trace.start`

Start recording executed instructions.

ParameterTypeRequiredDescription
`output_file`stringyesPath to output file
`pc_filter_start`numberFilter start address (default: 0)
`pc_filter_end`numberFilter end address (default: 65535)
`max_instructions`numberMax to record (default: 10000)
`include_registers`booleanInclude register state (default: false)

`vice.trace.stop`

Stop tracing and get statistics.

ParameterTypeRequiredDescription
`trace_id`stringyesTrace ID from `vice.trace.start`

Interrupt Logging

`vice.interrupt.log.start`

Start logging IRQ, NMI, and BRK events.

ParameterTypeRequiredDescription
`types`string[]Filter: `irq`, `nmi`, `brk` (default: all)
`max_entries`numberMax entries (default: 1000, max: 10000)

`vice.interrupt.log.stop`

Stop logging and retrieve all entries.

ParameterTypeRequiredDescription
`log_id`stringyesLog ID from `vice.interrupt.log.start`

`vice.interrupt.log.read`

Read entries without stopping the log.

ParameterTypeRequiredDescription
`log_id`stringyesLog ID
`since_index`numberReturn 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

Cocogitto — `feat:` 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

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

Frequently asked questions

What is vice-mcp?

vice-mcp is VICE emulator with an embedded MCP server for AI agents and automation

How do I install vice-mcp?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is vice-mcp open source?

Yes — it is hosted on GitHub at https://github.com/barryw/vice-mcp and has 4 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP