The toolchain note argued that AppleBridge’s integration points are its two automation surfaces, not its compiler — and that the boldest move is to stop compiling on the Mac and let the bridge deploy-and-run. This follow-up asks the practical question that raises: do the MCP tools actually support that, and what is missing? Read against the code, the answer is sharp — the toolset is mature where it drives a compiler and thin where it moves bytes and interacts with what runs. Captured as a design note on branch AppleBridge_mcp; not implemented.
The lens: two surfaces, seven tools
The toolchain note named AppleBridge’s two attachment points: Surface A, the DoScript/Apple-Event channel that drives a build and reads its output, and Surface B, the deploy-and-launch channel that pushes a file in, runs it, and observes the result. The seven MCP tools sort cleanly onto them:
| Surface | Tools today | Maturity |
|---|---|---|
| A — drive a build, read its output | mpw_execute, mac_compile, mac_read_file, mac_list_files | mature |
| B — move bytes, run and observe | mac_write_file, launch_app, mac_screenshot | thin |
Surface A is in good shape: mpw_execute covers the full MPW/ToolServer command set and returns STATUS/STDOUT/STDERR, and mac_compile wraps SC. The gaps are almost all on Surface B — which is precisely the surface the deploy-and-run idea depends on. That is the headline: the bridge is good at telling a 1990s compiler what to do and weak at getting bytes onto the machine and interacting with what runs.
flowchart TB
subgraph A["Surface A — drive build, read output (mature)"]
A1["mpw_execute"]
A2["mac_compile"]
A3["mac_read_file"]
A4["mac_list_files"]
end
subgraph B["Surface B — move bytes, run and observe (thin)"]
B1["mac_write_file (text-only, via Echo)"]
B2["launch_app"]
B3["mac_screenshot"]
end
subgraph P["Proposed additions"]
P1["mac_put_file / mac_get_file
binary + resource fork (MacBinary)"]
P2["mac_click / mac_type / mac_key / mac_menu"]
P3["mac_status (liveness)"]
P4["mac_build (one-shot, verified)"]
end
P1 -.fills.-> B
P2 -.fills.-> B
P3 -.spans.-> A
P4 -.spans.-> A
The gaps, in priority order
1. No binary or resource-fork file transfer — the keystone
mac_write_file is, literally, Echo '<content>' > '<path>' shelled through MPW. The consequences are not subtle: it is text only, it is MacRoman-converted, it breaks on any MPW metacharacter ({, }, ", ∂), and it is bounded by the daemon’s MAX_COMMAND_LENGTH of 8192 bytes — so it cannot write anything binary, anything large, or anything with a resource fork. mac_read_file (built on Catenate) corrupts binary content the same way on the way back. A small tell sits at the top of the tool module: base64 is imported and never used — binary transfer was foreseen and never built.
This single gap blocks the entire Surface-B vision. You cannot deploy a host-built 68K binary (the Retro68 path), you cannot ship an image, a resource file, or a test fixture, and you cannot pull a built application back to the host. Everything that surface is for runs through a door only wide enough for plain text.
The fix is a length-framed, fork-aware pair — mac_put_file / mac_get_file — carrying base64 payloads and, for executables, both forks via MacBinary, implemented as real daemon WRITEFILE/READFILE wire verbs rather than Echo-through-MPW. The wire protocol is already length-framed, so a binary file verb is a natural extension, and it simultaneously retires the metacharacter/size/encoding fragility of the current text path.
2. Launch-and-screenshot is observe-only — no input injection
launch_app foregrounds a GUI application and mac_screenshot shows its window, but there is no way to act on it: no click, no keystroke, no menu selection. The “watch it run” loop the toolchain note celebrated is only half a loop — the bridge can see a dialog but cannot press its button.
The fix is a small family of synthetic-event tools — mac_click(x, y), mac_type(text), mac_key(...), mac_menu(...) — posted daemon-side. Paired with the existing screenshot, they close the loop into a genuine GUI test cycle: drive a control, screenshot, verify. This is only worth much once a real binary can be deployed (gap 1), which is why it ranks second.
3. No status or liveness tool
When anything is down, every tool returns the same opaque "Mac not connected". Yet the daemon and host already track exactly what a caller needs: connection state, RX/TX counts, the heartbeat timestamp, and which helper processes (ToolServer) are running. None of it is exposed over MCP.
The fix is a cheap mac_status tool that surfaces that existing state — is the daemon connected, is ToolServer up, when was the last heartbeat, which helpers are alive. It is a disproportionate self-healing win for very little code.
4. No one-shot, verified build
A real build is several mpw_execute round-trips — SC, then Link, then Rez, then SetFile, then verify-by-artifact because long links return -1712 yet still succeed. The host already encodes that recipe in build.py, but it is not an MCP tool.
The fix is to expose mac_build as a single call returning structured pass/fail and parsed diagnostics — fewer round-trips, and the project’s hard-won build sequence captured in one place instead of reassembled each session.
5. Quality fixes on the existing tools
Smaller, but real: mac_list_files parses by splitting on whitespace, so filenames with spaces break; the robust binary write verb from gap 1 also retires the Echo fragility wholesale; and an optional region/crop argument on the screenshot would let a caller read a single dialog instead of decoding the full 1024×768 frame each time.
Other methods worth having
Two more, lower down but on-theme:
- A generic
mac_send_apple_event. The toolchain note’s CodeWarrior and THINK C paths are driven by Apple Events to a scriptable app. A tool that sends an arbitrary Apple Event (event class/ID + parameters) and harvests the reply generalises Surface A beyond ToolServer — the same channel, any scriptable participant. - Clipboard get/set. Basilisk II mirrors the clipboard between host and guest bidirectionally, which makes it a usable text side-channel — handy for small payloads when the file path is overkill.
Conclusion
The toolset is mature at driving the compiler and thin at moving bytes and interacting with what runs. Mapped onto the two surfaces, almost every gap is on Surface B — and gap 1, fork-aware binary transfer, is the keystone: it is the missing piece that turns the previous note’s “stop compiling on the Mac, let the bridge deploy-and-run” from a sketch into something usable, and it is the prerequisite that makes input injection (gap 2) worth building. The recommended order follows directly: a real mac_put_file/mac_get_file first, then the synthetic-event family, then the cheap mac_status and mac_build wrappers. Each is a self-contained addition to an MCP surface that has, so far, optimised for talking to a thirty-year-old compiler over actually carrying things to and from the machine.
Status: design note on branch AppleBridge_mcp; not implemented. The shipped MCP surface is the seven tools described here (mpw_execute, mac_compile, mac_read_file, mac_list_files, mac_write_file, launch_app, mac_screenshot). The additions sketched here extend the toolchain note’s two-surface framing from analysis into a concrete tooling backlog.

