Quick-start instructions for Claude Code users with the `claude mcp add` command and manual config file option. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
346 lines
11 KiB
Markdown
346 lines
11 KiB
Markdown
# 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
|