7.7 KiB
MCP Computer Lua Plan
Depends on the implemented host bridge in tools/mcp-bridge/.
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 implemented local/dev bridge link default is
ws://<host>:3001(CC_LINK_PORT, default3001). Production/public bridge deployments usews://<host>:4243withCC_LINK_PORT=4243; see../docs/public-ports.md. - The host-side MCP tool is named
probe-computersand 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.
- The implemented bridge accepts WebSocket connections on any path, so a bare local/dev URL such as
ws://<host>:3001is sufficient.
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 listener :3001 local/dev, :4243 production ]
Production deployments use the public ComputerCraft bridge WebSocket port 4243 instead of the local/dev default 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. The host bridge is already implemented and exposes MCP over plain HTTP JSON-RPC on MCP_PORT while this Lua program only speaks the ComputerCraft WebSocket link protocol.
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
mcp-computer ws://public.example.com:4243
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.
Link Protocol
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(), ornilencoded as JSON null/omitted depending ontextutils.serializeJSONbehavior. The bridge treats missing, empty, or non-string labels asnull.
Hello OK
Expected from bridge:
{
"type": "hello-ok"
}
The bridge sends hello-ok immediately after a valid hello. The Lua program should wait briefly for this frame so connection or protocol problems are obvious, then proceed only after receiving it.
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, andversion. - 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
httpexists. - Check
http.websocketexists. - Call
http.websocket(url). - On failure, print the returned error and exit non-zero if possible.
- Send
helloframe. - Optionally wait up to a short timeout for
hello-ok.
3. Request Loop
- Receive websocket messages in a loop.
- Decode JSON with
textutils.unserializeJSONinsidepcall. - Ignore or respond with error for malformed messages.
- Handle
terminatecleanly if usingparallel.waitForAnyaround websocket receive and terminate watcher. - For
requestwithmethod = '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 = 'null';
end
return 'pong from ' .. tostring(os.getComputerID()) .. ' (Label: ' .. tostring(label) .. ')';
end
Keep the output aligned with the implemented bridge's formatComputer fallback (null for missing labels) and the MCP tool's expected successful pong lines.
5. Packaging
- Add
programs/mcp-computer.luatopackages/trapos-sandbox/ccpm.json. - Bump
trapos-sandboxversion. - Mirror the version bump in
packages/index.json. - Do not add it to
autostartin the first pass. - Do not add
trapos-sandboxas atraposdependency 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/decodehelpers 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. The bridge already includes integration-test Lua clients under tools/mcp-bridge/test-integration/lua/ that can be used as protocol references. 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 checkjust testif tests are added or changed.
Manual Validation
- Start the TypeScript bridge.
- On one ComputerCraft computer, run
mcp-computer ws://<bridge-host>:3001for local/dev, ormcp-computer ws://<public-host>:4243for public production. - Confirm the bridge logs the computer registration.
- Connect an MCP client to the bridge MCP port.
- Call
probe-computers. - Confirm response includes the computer id and label.
- 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.luaintrapos-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
pingrequests.