# MCP Computer Lua Plan ## Goal Add a TrapOS sandbox program that links a ComputerCraft computer to the host-side MCP bridge over WebSocket. The first supported command is `ping`, used by the bridge's MCP tool `probe-computers`. The Lua program answers: ```text pong from (Label: ) ``` ## Decisions - Lua program path: `programs/mcp-computer.lua`. - Package: `trapos-sandbox`. - The program connects outbound to the bridge's ComputerCraft link port. - The bridge link default is `ws://:3001`. - The host-side MCP tool is named `probe-computers` and broadcasts to every connected computer. - No link auth for the first version. - Keep the first Lua implementation as a program, not an autostart server, until the bridge loop is proven. ## Background CC:Tweaked cannot listen on real HTTP/TCP ports with standard APIs. It can connect outward using `http.websocket`. This program is therefore the in-game half of the bridge: ```text [ CC computer ] --outbound WebSocket--> [ tools/mcp-bridge link port :3001 ] ``` The Lua program is effectively an agent. It identifies itself to the bridge, waits for JSON request frames, executes supported methods, and sends JSON response frames. ## User Interface Program usage: ```text mcp-computer mcp-computer -url mcp-computer --version mcp-computer --help ``` Examples: ```text mcp-computer ws://192.168.1.20:3001 mcp-computer -url ws://mcp-bridge.local:3001 ``` The program should print clear status lines: ```text mcp-computer v0.1.1 connecting to ws://192.168.1.20:3001 linked as 12 (Label: base-turtle) waiting for requests... Press Ctrl+T to stop. ``` If `http` or `http.websocket` is unavailable, print a clear error explaining that CC:Tweaked HTTP/WebSocket must be enabled. ## Link Protocol All frames are JSON strings compatible with `textutils.serializeJSON` and `textutils.unserializeJSON`. ### Computer Hello Sent immediately after opening the websocket: ```json { "type": "hello", "computerId": 12, "computerLabel": "base-turtle" } ``` Lua fields: - `computerId`: `os.getComputerID()`. - `computerLabel`: `os.getComputerLabel()`, or `nil` encoded as JSON null/omitted depending on `textutils.serializeJSON` behavior. ### Hello OK Expected from bridge: ```json { "type": "hello-ok" } ``` The first version may continue even if `hello-ok` is not received immediately, but implementation should prefer waiting briefly so connection problems are obvious. ### Probe Request Received from bridge: ```json { "type": "request", "id": "req-123", "method": "ping" } ``` ### Probe Response Sent back by Lua: ```json { "type": "response", "id": "req-123", "ok": true, "result": "pong from 12 (Label: base-turtle)" } ``` Unknown method response: ```json { "type": "response", "id": "req-123", "ok": false, "error": "unknown method" } ``` ## Implementation Sections ### 1. Program Skeleton - Add `programs/mcp-computer.lua`. - Support `--help`, `-help`, `help`, `--version`, `-version`, and `version`. - Version output uses `require('/apis/libversion')().forSelf()`. - Parse URL from first positional argument or `-url `. - Reject missing URL with usage. ### 2. Connection Handling - Check `http` exists. - Check `http.websocket` exists. - Call `http.websocket(url)`. - On failure, print the returned error and exit non-zero if possible. - Send `hello` frame. - Optionally wait up to a short timeout for `hello-ok`. ### 3. Request Loop - Receive websocket messages in a loop. - Decode JSON with `textutils.unserializeJSON` inside `pcall`. - Ignore or respond with error for malformed messages. - Handle `terminate` cleanly if using `parallel.waitForAny` around websocket receive and terminate watcher. - For `request` with `method = 'ping'`, send success response. - For unknown request methods, send error response. - Close websocket on exit. ### 4. Pong Formatting Implement a local function: ```lua local function formatPong() local label = os.getComputerLabel(); if not label or label == '' then label = 'nil'; end return 'pong from ' .. tostring(os.getComputerID()) .. ' (Label: ' .. tostring(label) .. ')'; end ``` Keep the output exactly aligned with the bridge plan. ### 5. Packaging - Add `programs/mcp-computer.lua` to `packages/trapos-sandbox/ccpm.json`. - Bump `trapos-sandbox` version. - Mirror the version bump in `packages/index.json`. - Do not add it to `autostart` in the first pass. - Do not add `trapos-sandbox` as a `trapos` dependency unless explicitly desired later. ## Testing Strategy ### Unit-Style Lua Tests Prefer moving deterministic protocol helpers into `apis/libmcpcomputer.lua` only if testing the program directly becomes awkward. The minimal testable API could expose: - `formatPong(osLike)`. - `handleRequest(request, osLike)`. - `encode/decode` helpers if needed. If a helper API is added, include it in `trapos-sandbox` and add tests under `tests/` using `/apis/libtest.lua`. If keeping everything in one program, at least verify syntax and help/version behavior with CraftOS-PC probes. ### CraftOS-PC Probes Use automated probes only; do not run `just repl`. Examples after implementation: ```bash just trapos-exec 'shell.run("/programs/mcp-computer.lua", "--help")' just trapos-exec 'shell.run("/programs/mcp-computer.lua", "--version")' ``` For an end-to-end probe, run the TS bridge on localhost and use CraftOS-PC with HTTP local access enabled if the harness permits it. If localhost access is blocked by CC:Tweaked config, document the limitation and rely on an in-game/manual validation for the WebSocket connection. ### Required Repo Checks After editing Lua or package descriptors: - `just check` - `just test` if tests are added or changed. ## Manual Validation 1. Start the TypeScript bridge. 2. On one ComputerCraft computer, run `mcp-computer ws://:3001`. 3. Confirm the bridge logs the computer registration. 4. Connect an MCP client to the bridge MCP port. 5. Call `probe-computers`. 6. Confirm response includes the computer id and label. 7. Connect a second computer and confirm the tool returns two lines. ## Out Of Scope For First Pass - Autostart server behavior. - Reconnect/backoff loop. - Authentication. - Commands that mutate the world. - Turtle/peripheral control. - MCP protocol implementation inside Lua. Lua only speaks the simple bridge link protocol. ## Deliverables - `programs/mcp-computer.lua` in `trapos-sandbox`. - Package version bump for `trapos-sandbox`. - Optional helper API and tests if implementation benefits from unit coverage. - Working WebSocket link to `tools/mcp-bridge`. - Correct response to bridge `ping` requests.