opencode-mcp

opencode-mcp

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.

Category
Visit Server

README

opencode-mcp

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).

Quick Start (local testing)

# 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.

Architecture

┌──────────────────────────────────────────────┐
│        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.

MCP Tools

Tool Input Description
list_instances List all discovered opencode instances
refresh_instances Re-scan registry, health-check, return updated list
list_sessions instance List sessions with ID, title, status
get_session instance, session_id, message_limit? Session details + last N messages
create_session instance, title? Create a new chat session
send_message instance, session_id, message, async? Send a prompt (sync or async)
get_status instance Status of all sessions (idle/busy/retry)
abort_session instance, session_id Abort a running session

Instance names support fuzzy substring matching (e.g. "laptop" matches "laptop-myproject"). Session IDs accept prefixes (e.g. "ses_3149").

Environment Variables

MCP server

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)

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

Registration File Format

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.

Connecting an OpenCode Instance

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 user@relay.example.com"
opencode-connected

# Pass extra args to opencode (after --)
opencode-connected -- -d

The script:

  1. Picks a random available local port (4096-5095)
  2. Starts opencode TUI with --port (enables HTTP side-car on 127.0.0.1)
  3. If RELAY_SSH_CMD is set: establishes SSH reverse tunnel with auto-retry
  4. Registers the instance (lazily creates the registry directory)
  5. Cleans up the registration file on exit

Note: opencode without --port does not start an HTTP server. The --port flag is what enables the HTTP side-car alongside the TUI.

For work machines with different MCP configs, set OPENCODE_CONFIG in your shell profile — the script does not handle config selection.

Integration with mcp-gateway (Docker)

To add opencode-mcp to an existing mcp-gateway Docker deployment:

1. Install from npm

npx -y opencode-mcp  # or add to gateway's SERVERS dict

2. Docker configuration

# 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.

3. MCP server config in mcp-gateway

Add to the gateway's server configuration:

{
  "mcpServers": {
    "opencode": {
      "command": "npx",
      "args": ["-y", "opencode-mcp"],
      "transport": "stdio",
      "env": {
        "RELAY_REGISTRY_DIR": "/tmp/opencode-relay"
      }
    }
  }
}

4. Verify

# 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:
# list_instances → sees the connected instance
# list_sessions → sees its sessions
# send_message → interacts with it

Project Structure

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/
│       ├── instances.ts         # list_instances, refresh_instances
│       ├── sessions.ts          # list_sessions, get_session, create_session
│       └── messages.ts          # send_message, get_status, abort_session
├── scripts/
│   └── opencode-connected       # Client: random port + tunnel + exec opencode TUI
├── plans/
│   └── architecture.md          # Design doc + future work
├── package.json
├── tsconfig.json
└── .env.example

Development

npm install
npm run dev          # run with tsx (no build step)
npm run build        # compile TypeScript
npm start            # run compiled output

Security

  • SSH tunnels: the auth boundary — standard SSH key or gcloud auth
  • Tunnel ports: bound to host's localhost only, not externally accessible
  • OpenCode binding: 127.0.0.1 by default — not network-accessible
  • MCP transport: stdio (no network exposure); OAuth via mcp-gateway
  • Registration files: contain only name, hostname, port, cwd — no credentials

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured