# 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
```bash
# 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)
```bash
npx @simen/vice-mcp
```
### From GitHub
```bash
npx github:simen/vice-mcp
```
### Local Development
```bash
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:**
```bash
x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502
```
**2. Add the MCP server:**
```bash
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`:
```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):
```json
{
"mcpServers": {
"vice": {
"command": "npx",
"args": ["@simen/vice-mcp"]
}
}
}
```
Or for local development:
```json
{
"mcpServers": {
"vice": {
"command": "node",
"args": ["/path/to/vice-mcp/dist/index.js"]
}
}
}
```
## Tool Reference
### Connection & Status
| Tool | Description |
|------|-------------|
| `connect` | Connect to VICE (default: 127.0.0.1:6502) |
| `disconnect` | Disconnect from VICE |
| `status` | Get connection state and emulation status |
### Memory Operations
| Tool | Description |
|------|-------------|
| `readMemory` | Read raw bytes with hex dump and ASCII |
| `writeMemory` | Write bytes to memory |
### CPU & Execution
| Tool | Description |
|------|-------------|
| `getRegisters` | Get A, X, Y, SP, PC, and flags (interpreted) |
| `step` | Single-step execution (with step-over option) |
| `continue` | Resume execution |
| `reset` | Soft or hard reset |
| `runTo` | Run until specific address (temporary breakpoint) |
| `disassemble` | Disassemble 6502 code with KERNAL labels |
### Breakpoints & Watchpoints
| Tool | Description |
|------|-------------|
| `setBreakpoint` | Set execution breakpoint |
| `deleteBreakpoint` | Remove breakpoint or watchpoint |
| `listBreakpoints` | List all breakpoints |
| `toggleBreakpoint` | Enable/disable breakpoint |
| `setWatchpoint` | Set memory read/write watchpoint |
| `listWatchpoints` | List all watchpoints |
### Semantic Layer (Interpreted C64 Data)
| Tool | Description |
|------|-------------|
| `readScreen` | Get screen as text (PETSCII decoded) with summary mode |
| `readColorRam` | Get color RAM with color names and usage stats |
| `readVicState` | Full VIC-II state: graphics mode, colors, banks, sprites |
| `readSprites` | All 8 sprites: position, visibility, colors, pointers |
### Visual Feedback
| Tool | Description |
|------|-------------|
| `screenshot` | Capture display buffer with palette |
| `renderScreen` | ASCII art rendering of display |
### State Management
| Tool | Description |
|------|-------------|
| `saveSnapshot` | Save complete machine state to file |
| `loadSnapshot` | Load machine state from file |
| `loadProgram` | 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 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:
```json
{
"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 |
|------|---------|
| `src/index.ts` | MCP server, tool definitions, semantic layer |
| `src/protocol/client.ts` | VICE binary monitor client |
| `src/protocol/types.ts` | Protocol constants and types |
| `src/utils/c64.ts` | C64 utilities (PETSCII, colors, VIC banks) |
| `src/utils/disasm.ts` | 6502 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](https://vice-emu.sourceforge.io/vice_13.html). 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