Remote-control classic Mac OS (System 7+) from a modern host or an LLM. 68k first; PPC and real hardware on the roadmap.
A tiny background app on the guest speaks a framed-JSON protocol over MacTCP. A Rust client library, a developer CLI, and an MCP server on the host drive it. Any MCP-aware LLM (Claude Code, Claude Desktop) can then operate the guest directly — take screenshots, click, type, send Apple Events, read files, inspect resource forks, self-update.
Tested against MAME's macii target and expected to work on any 68k
System 7 machine with MacTCP configured. PPC and real hardware are on
the roadmap but not yet exercised.
agent/ # Guest-side C, cross-compiled with Retro68
src/main.c event loop + per-conn state machine
src/transport_mactcp.c MacTCP shim (async I/O + notifier)
src/methods_*.c one file per method group
src/packbits.c streaming decoder for wire compression
src/ae_desc.c Apple Event JSON ↔ AEDesc encoder/decoder
src/jgne_filter.c cross-app input hook (research; not wired)
build-68k.sh wraps CMake + Retro68; stamps a fresh version
crates/
mc-agent-client/ Rust protocol library (no CLI)
mc-ocr/ macOS Vision OCR helper wrapper
mc-pict/ classic PICT → PNG decoder
mc-mac-roman/ MacRoman ↔ UTF-8 codec
bin/
mc-cli/ developer CLI: hello/health, capture, click,
fs.*, ae-send, res.*, aete, update, ...
mac-controld/ MCP server: 26 tools mapped from mc-cli
plan.md Master vision / north-star
todos.md Backlog + discovered problems
AGENTS.md Orientation for LLM agents working in the tree
Prereq: Retro68 built at
~/opt/Retro68-build/toolchain (or RETRO68_ROOT set elsewhere).
# Guest binary (68k) + 800 KB floppy image.
./agent/build-68k.sh
# → agent/dist/mc-agent-68k.bin (MacBinary, both forks)
# → agent/dist/mc-agent-68k.dsk (HFS, drop `mc-agent` into Startup Items)
# Host tools.
cargo build --release
# Point at a running MAME / real Mac with MacTCP configured.
./target/release/mc-cli --host <guest-ip> hello
./target/release/mc-cli --host <guest-ip> healthPush a new agent build over the wire (no floppy swaps):
./target/release/mc-cli --host <guest-ip> update \
--binary agent/dist/mc-agent-68k.bin \
--version <stamp-from-build-output> \
--compress packbitsRegister the MCP server so an LLM can drive the guest:
claude mcp add --scope project mac-control \
./target/release/mac-controld -- --host <guest-ip>- Screen: capture, click / drag / type / key, OCR-based click-by-label.
- Files: list, stat, get, put (with optional PackBits compression), hash, copy, move, delete. Full MacBinary support for both forks.
- Processes: list, launch, front, quit.
- Apple Events: send arbitrary events with typed parameters (text, int, bool, ostype, list, record, raw); decode replies back to JSON.
- Resource forks: enumerate, extract, parse AETE terminology so an LLM can discover an app's Apple Event vocabulary.
- Self-update: stage → apply → reconnect → smoke-test → commit dance with automatic rollback on failure.
plan.md— the vision this is executing against.todos.md— backlog + gotchas we've hit and want to remember.AGENTS.md— orientation for LLMs / agents working in this tree.
See CONTRIBUTING.md.
MIT — see LICENSE.