loading…
Search for a command to run...
loading…
An MCP server that enables discovery and interaction with multiple OpenCode instances across different machines using SSH reverse tunnels. It provides tools for
An MCP server that enables discovery and interaction with multiple OpenCode instances across different machines using SSH reverse tunnels. It provides tools for listing instances, managing chat sessions, and sending messages to remote coding environments.
An MCP server that discovers, monitors, and drives multiple OpenCode instances running across personal machines. Uses SSH reverse tunnels through a central relay for discovery and transport. Pluggable transport layer supports future backends (Tailscale, Cloudflare Tunnels, mDNS).
# 1. Install
npm install && npm run build
# 2. Start opencode with HTTP side-car (in a separate terminal)
# opencode-connected picks a random port and writes a registration file
ln -s ~/prg/opencode-mcp/scripts/opencode-connected ~/bin/opencode-connected
opencode-connected
# 3. Run with MCP inspector (in another terminal)
npx @modelcontextprotocol/inspector tsx src/index.ts
# Or run directly (stdio MCP server)
node dist/index.js
Both opencode-connected and the MCP server default to /tmp/opencode-relay
for the registry directory — no configuration needed for local testing.
┌──────────────────────────────────────────────┐
│ Relay machine (GCE / VPS / etc.) │
│ │
│ mcp-gateway ──── opencode-mcp (stdio) │
│ │ │ │
│ │ reads /tmp/opencode-relay/ │
│ │ or RELAY_REGISTRY_DIR │
│ │ │ │
│ OAuth localhost:10001 ──┐ │
│ front localhost:10002 ──┤ opencode│
│ localhost:10003 ──┘ APIs │
│ │
│ sshd: accepts reverse tunnels │
└──────▲──────────▲───────────▲────────────────┘
│ │ │
ssh -R ssh -R ssh -R
│ │ │
laptop desktop laptop
(oc:4823) (oc:4567) (oc:4901)
The MCP server runs on the same machine that accepts SSH reverse tunnels.
It reads registration JSON files from a directory, health-checks each
registered port on localhost, and creates OpenCode SDK clients for healthy
instances. All OpenCode API calls go through localhost:{tunnel_port}.
OpenCode binds to 127.0.0.1 (default) — the SSH tunnel is the auth
boundary. No passwords needed.
| Tool | Input | Description |
|---|---|---|
instances |
— | List all discovered instances with status (idle/busy) and recent session |
send |
instance, message, abort? |
Send a message to the most recent session; set abort=true to stop a running task |
read |
instance, message_limit? |
Read the last N messages from the most recent session |
Instance names support fuzzy substring matching (e.g. "laptop" matches
"laptop-myproject").
| Variable | Default | Description |
|---|---|---|
RELAY_REGISTRY_DIR |
/tmp/opencode-relay |
Directory containing registration JSON files |
DISCOVERY_INTERVAL_MS |
30000 |
How often to refresh instance list (ms) |
HEALTH_CHECK_TIMEOUT_MS |
3000 |
Timeout for health-checking each instance (ms) |
TRANSPORT |
local-relay |
Transport backend (local-relay, future: tailscale) |
SEND_TIMEOUT_MS |
300000 |
Timeout for streaming send responses (ms) |
opencode-connected script| Variable | Default | Description |
|---|---|---|
RELAY_SSH_CMD |
— | SSH command to reach relay. If unset, local only. |
RELAY_REGISTRY_DIR |
/tmp/opencode-relay |
Registry directory (local or on relay) |
INSTANCE_NAME |
$(hostname)-$(basename $PWD) |
Instance name for registration |
Each file in RELAY_REGISTRY_DIR is a JSON file named {instance-name}.json:
{
"name": "laptop-myproject",
"hostname": "laptop",
"port": 10042,
"localPort": 4823,
"cwd": "/home/user/projects/myproject",
"connectedAt": "2026-03-14T10:30:00Z"
}
Files are written by opencode-connected (locally or on the relay via SSH).
The MCP server prunes files whose ports fail health checks.
Use opencode-connected instead of bare opencode to start the TUI with
an HTTP side-car:
# Install (symlink)
ln -s ~/prg/opencode-mcp/scripts/opencode-connected ~/bin/opencode-connected
# Local only (no tunnel, writes registration to /tmp/opencode-relay/)
opencode-connected
# With relay (set RELAY_SSH_CMD in your shell profile)
export RELAY_SSH_CMD="gcloud compute ssh mcp-gateway --zone=us-central1-a --project=my-project --"
opencode-connected
# Or with direct SSH
export RELAY_SSH_CMD="ssh [email protected]"
opencode-connected
# Pass extra args to opencode (after --)
opencode-connected -- -d
The script:
--port (enables HTTP side-car on 127.0.0.1)RELAY_SSH_CMD is set: establishes SSH reverse tunnel with auto-retryNote: opencode without --port does not start an HTTP server.
The --port flag is what enables the HTTP side-car alongside the TUI.
Multiple instances in the same directory: The instance name defaults to
$(hostname)-$(basename $PWD). If you run multiple opencode instances in
the same directory, they'll compete for the same registration file — the
last one wins and the others become invisible to the MCP server. To avoid
this, set INSTANCE_NAME explicitly:
INSTANCE_NAME=my-tests opencode-connected
INSTANCE_NAME=my-refactor opencode-connected
For work machines with different MCP configs, set OPENCODE_CONFIG in your
shell profile — the script does not handle config selection.
To add opencode-mcp to an existing mcp-gateway Docker deployment:
npx -y opencode-mcp # or add to gateway's SERVERS dict
# docker run additions:
--network=host # reach SSH tunnel ports on host's localhost
-v /tmp/opencode-relay:/tmp/opencode-relay:ro # read registration files
-e RELAY_REGISTRY_DIR=/tmp/opencode-relay
--network=host is required because SSH reverse tunnels bind on the
host's localhost. The container needs to reach those ports directly.
Add to the gateway's server configuration:
{
"mcpServers": {
"opencode": {
"command": "npx",
"args": ["-y", "opencode-mcp"],
"transport": "stdio",
"env": {
"RELAY_REGISTRY_DIR": "/tmp/opencode-relay"
}
}
}
}
# On a client machine:
export RELAY_SSH_CMD="gcloud compute ssh mcp-gateway --zone=us-central1-a --project=my-project --"
opencode-connected
# From the chat interface, the LLM can now call:
# instances → sees the connected instance
# send → interacts with it
# read → sees what's been happening
opencode-mcp/
├── src/
│ ├── index.ts # MCP server entry + transport factory
│ ├── types.ts # RegistrationFile, OpenCodeInstance
│ ├── registry.ts # Instance cache + OpenCode SDK client mgmt
│ ├── transport/
│ │ ├── interface.ts # Abstract Transport interface
│ │ └── local-relay.ts # File-based registry + localhost health checks
│ └── tools/
│ └── simplified.ts # instances, send, read
├── scripts/
│ └── opencode-connected # Client: random port + tunnel + exec opencode TUI
├── plans/
│ └── architecture.md # Design doc + future work
├── package.json
├── tsconfig.json
└── .env.example
npm install
npm run dev # run with tsx (no build step)
npm run build # compile TypeScript
npm start # run compiled output
127.0.0.1 by default — not network-accessibleДобавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"opencode-mcp": {
"command": "npx",
"args": []
}
}
}Read, send and search emails from Claude
Send, search and summarize Slack messages
No-code MCP client for team chat platforms, such as Slack, Microsoft Teams, and Discord.
A community discord server dedicated to MCP by [Frank Fiegel](https://github.com/punkpeye)