6.9 KiB
MCP Bridge Plan
Goal
Build a small TypeScript bridge that lets MCP clients call tools backed by live ComputerCraft computers.
The first MCP tool is probe-computers. It broadcasts a probe request to every linked computer and returns one line per response:
pong from <computerId> (Label: <computerLabel>)
Decisions
- Host-side implementation lives in
tools/mcp-bridge/. - MCP clients connect on
MCP_PORT, default3000. - ComputerCraft computers connect on
CC_LINK_PORT, default3001. - The MCP port and ComputerCraft link port are separate listeners.
- No auth is required for the first bridge implementation.
probe-computerstakes no arguments and probes every currently linked computer.- The bridge owns real HTTP/MCP transport. ComputerCraft computers connect outbound over WebSocket.
Background
CC:Tweaked computers cannot bind a real TCP/HTTP port with the standard APIs. They can make outbound HTTP/WebSocket connections. Therefore the host bridge exposes real MCP over HTTP and maintains outbound WebSocket links from computers.
The current MCP TypeScript SDK situation is split:
@modelcontextprotocol/sdkv1 is stable and commonly used by existing examples.- Newer docs describe split packages such as
@modelcontextprotocol/serverand@modelcontextprotocol/node, but the upstream README says that branch is v2/pre-alpha as of this research.
Prefer stable v1 for the first implementation unless opencode compatibility requires the newer packages. Re-check package docs immediately before implementation.
Architecture
[ opencode / MCP client ] --HTTP MCP--> [ tools/mcp-bridge ] --WebSocket--> [ CC computer(s) ]
:3000 :3001
The bridge has two independent surfaces:
- MCP listener: streamable HTTP MCP endpoint for agents.
- Link listener: WebSocket endpoint for ComputerCraft computers.
The bridge keeps an in-memory registry of connected computers:
type ComputerConnection = {
computerId: number;
label: string | null;
ws: WebSocket;
connectedAt: number;
lastSeenAt: number;
};
Link Protocol
All ComputerCraft link messages are JSON text frames.
Computer Hello
Sent by the Lua program immediately after opening the WebSocket:
{
"type": "hello",
"computerId": 12,
"computerLabel": "base-turtle"
}
Bridge behavior:
- Validate
computerIdis a number. - Treat missing/empty
computerLabelasnull. - Register or replace the existing connection for that
computerId. - Reply with
hello-ok.
Hello OK
{
"type": "hello-ok"
}
Probe Request
Sent by the bridge when MCP tool probe-computers is called:
{
"type": "request",
"id": "req-123",
"method": "ping"
}
Probe Response
Sent by each Lua computer:
{
"type": "response",
"id": "req-123",
"ok": true,
"result": "pong from 12 (Label: base-turtle)"
}
Error shape, reserved for later commands:
{
"type": "response",
"id": "req-123",
"ok": false,
"error": "unknown method"
}
MCP Tool Behavior
Tool name: probe-computers.
Input schema: no arguments.
Behavior:
- Snapshot the current connected computer registry.
- If none are connected, return
No computers connected.. - Generate one request id per computer, or one shared batch id with per-computer tracking.
- Send a
pingrequest to every linked computer. - Wait for responses until either all answer or the probe timeout expires.
- Return text with one line per successful response.
- Include timeout lines for computers that did not answer.
Suggested timeout: CC_PROBE_TIMEOUT_MS, default 2000.
Example output:
pong from 12 (Label: base-turtle)
pong from 13 (Label: miner-1)
timeout from 14 (Label: farm-turtle)
Project Layout
tools/mcp-bridge/
package.json
package-lock.json
tsconfig.json
src/
index.ts
link-server.ts
mcp-server.ts
protocol.ts
test/
protocol.test.ts
probe-computers.test.ts
Keep the first implementation minimal. Collapse files if the code is clearer in fewer modules.
Implementation Sections
1. Tooling Setup
- Create
tools/mcp-bridge/package.json. - Use TypeScript with strict checks.
- Use Node's built-in test runner if practical, or Vitest if SDK/test ergonomics require it.
- Add scripts:
npm run buildnpm testnpm run devnpm start
2. Link Server
- Start WebSocket server on
CC_LINK_PORT. - Accept JSON text frames only.
- Register computers after valid
hello. - Remove computers on close/error.
- Track pending request resolvers by request id.
- Ensure malformed frames do not crash the process.
3. MCP Server
- Start MCP HTTP transport on
MCP_PORT. - Register tool
probe-computers. - Implement tool response as MCP text content.
- Keep ordinary
/healthendpoint available on the MCP listener if the selected transport/framework allows it without fighting the SDK.
/health response should be normal HTTP, not MCP:
{
"ok": true,
"computers": 2
}
4. Configuration
Environment variables:
MCP_HOST, default127.0.0.1.MCP_PORT, default3000.CC_LINK_HOST, default0.0.0.0.CC_LINK_PORT, default3001.CC_PROBE_TIMEOUT_MS, default2000.
5. Verification
Unit tests:
- Protocol validation accepts valid
helloand rejects invalid frames. probe-computersreturnsNo computers connected.when registry is empty.probe-computersaggregates multiple successful responses.probe-computersreports timeout for a connected computer that does not answer.
Integration tests:
- Start bridge on ephemeral ports.
- Connect fake WebSocket computer clients.
- Call the probe path through the MCP handler, or through a thin internal function if the SDK transport is hard to drive in tests.
Manual/agent checks:
npm run buildfromtools/mcp-bridge.npm testfromtools/mcp-bridge.- Use opencode headless mode only for critical MCP compatibility checks after the bridge can run locally.
Open Questions To Re-check During Implementation
- Exact HTTP MCP transport API for the chosen stable SDK version.
- Whether opencode expects streamable HTTP only, SSE compatibility, or can use stdio. This bridge should prioritize HTTP because the requirement is an MCP port.
- Whether tool names with hyphens are accepted cleanly by the MCP clients we care about. If not, challenge
probe-computersand useprobe_computers.
Out Of Scope For First Pass
- Authentication and authorization.
- Persistent computer registry.
- Commands other than
ping/probe-computers. - Multi-bridge clustering.
- TLS termination. Put the bridge behind a reverse proxy if needed later.
Deliverables
tools/mcp-bridge/TypeScript project.- MCP HTTP listener on port
3000by default. - Computer WebSocket link listener on port
3001by default. - MCP tool
probe-computersreturning live ComputerCraft pong lines. - Tests for protocol parsing and probe aggregation.