cc-libs/.plans/mcp-computer-lua-plan.md

6.6 KiB

MCP Computer Lua Plan

Relates to ./mcp-bridge-plan.md

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:

pong from <computerId> (Label: <computerLabel>)

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://<host>: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:

[ 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:

mcp-computer <ws-url>
mcp-computer -url <ws-url>
mcp-computer --version
mcp-computer --help

Examples:

mcp-computer ws://192.168.1.20:3001
mcp-computer -url ws://mcp-bridge.local:3001

The program should print clear status lines:

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.

All frames are JSON strings compatible with textutils.serializeJSON and textutils.unserializeJSON.

Computer Hello

Sent immediately after opening the websocket:

{
  "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:

{
  "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:

{
  "type": "request",
  "id": "req-123",
  "method": "ping"
}

Probe Response

Sent back by Lua:

{
  "type": "response",
  "id": "req-123",
  "ok": true,
  "result": "pong from 12 (Label: base-turtle)"
}

Unknown method response:

{
  "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 <ws-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:

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:

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://<bridge-host>: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.