Run shell commands, manage processes, and read/write files on remote machines through an MCP server — so an LLM client (Claude, ChatGPT, etc.) can operate them directly.
- Agent — a small process that runs on each machine you want to control. Connects out to the Gateway over WebSocket; never listens for inbound connections itself.
- Gateway — a single server that Agents connect to, and that exposes one MCP server (Streamable HTTP) for LLM clients to call. Multiplexes many Agents behind one MCP endpoint.
LLM client --MCP (HTTPS)--> Gateway <--WebSocket-- Agent (device A)
^
'-----WebSocket----- Agent (device B)
The Gateway exposes focused inspection tools so an Agent can read common state without running an arbitrary command. Each tool selects a fixed operation on the selected device and is marked read-only in MCP metadata:
- Git:
git_status,git_diff,git_logread a working tree at a supplied repository path. Status disables optional index locks; diff disables external diff and text conversion. - Docker:
docker_ps,docker_inspect,docker_logslist containers, show selected state and image fields, or read a bounded log tail. Container logs are limited to 500 lines and at most the last seven days. - systemd:
systemd_status,systemd_units,journal_queryinspect the current user's services and unit logs. Journal reads are limited to 500 lines and the last 30 days. - tmux:
tmux_sessions,tmux_panes,tmux_captureinspect existing sessions and read a bounded pane history without starting a tmux server. - GitHub:
github_repo,github_issue,github_pull_requestread repository, issue, and pull request metadata fromapi.github.com. Public resources do not require a token; setGH_TOKENorGITHUB_TOKENin the Agent environment to access private repositories or authenticated API limits.
Outputs are bounded, and the Agent accepts only typed selectors and limits for these tools; it does not accept a shell command or executable path. Tools that need a host utility return an unsupported error if that utility is unavailable. Existing command_exec and sandboxed command_read remain available for other tasks.
⚠️ /mcphas no authentication. Anyone who can reach it can run commands on every connected Agent. Do not expose it to an untrusted network without your own reverse-proxy-level access control./mcp(MCP_LISTEN_ADDRESS, default:8080) and/agent/ws(AGENT_LISTEN_ADDRESS, default:8081) listen on separate ports, so you can expose only the/mcpport through a public tunnel while keeping the Agent port scoped to Agents only.
Published to GHCR on every merge to master:
docker run -p 8080:8080 -p 8081:8081 \
-e AGENT_SHARED_SECRET=secret \
ghcr.io/tomacheese/command-relay-mcp:latestSee the Releases page for versioned tags.
Download the command-relay-agent binary for your architecture from the Releases page (Linux only — Landlock-based sandboxing for command_read is Linux-specific), then run it as a user systemd service using deploy/systemd/command-relay-agent.service — the sandbox creates its own unprivileged user/network namespaces at runtime, so no elevated systemd identity (DynamicUser, root) is needed:
sudo cp command-relay-agent /usr/local/bin/
mkdir -p ~/.config/systemd/user
cp deploy/systemd/command-relay-agent.service ~/.config/systemd/user/
systemctl --user edit command-relay-agent # set DEVICE_ID / DEVICE_SECRET / GATEWAY_URL
loginctl enable-linger "$USER" # keep it running after logout
systemctl --user enable --now command-relay-agentAuto-update is enabled by default (set AUTO_UPDATE_ENABLED=false to disable it). When it runs, the Agent replaces its own running binary file with the new one. If the binary lives in a root-owned path that the unprivileged user cannot write to, such as the sudo cp ... /usr/local/bin/ above, the replacement fails, is only logged, and auto-update does not work. To use auto-update, place the binary somewhere the user running the Agent can write (for example ~/.local/bin/command-relay-agent) and override ExecStart to that path with systemctl --user edit.
go build ./...
go vet ./...
go test ./...
docker build -t command-relay-mcp .See AGENTS.md for contributor and coding-agent guidance.