Skip to main content
Glama
OddbeakerLLC

Remote MCP Server

by OddbeakerLLC
README.md
# mcp-remote-server

A lightweight MCP (Model Context Protocol) server that runs on a remote machine, giving AI tools like Claude access to that machine over HTTPS.

## What it does

Exposes four tools via a single `/mcp` HTTP endpoint:

| Tool | Description |
|------|-------------|
| `run_command` | Run a shell command on the remote server |
| `read_file` | Read a file from the remote server |
| `write_file` | Write content to a file on the remote server |
| `list_directory` | List contents of a directory on the remote server |

## Quick start

The automated installer handles everything — user creation, SSL certificates, systemd service, and firewall detection:

```bash
git clone https://github.com/OddbeakerLLC/mcp-remote-server.git
cd mcp-remote-server
sudo bash setup.sh
```

The installer will:
1. Create a dedicated `mcp-server` system user
2. Detect whether port 443 is available
   - **Free** → obtains a Let's Encrypt certificate and runs HTTPS directly
   - **In use** → runs HTTP on port 3098 and prints a reverse proxy config snippet for your web server
3. Create and enable a systemd service with auto-restart
4. Print your connector URL

## Connecting to claude.ai

This server is designed to be used as an MCP connector on [claude.ai](https://claude.ai):

1. Open **claude.ai** and go to **Settings**
2. Navigate to **Connectors** (or **MCP Connectors**)
3. Click **Add connector**
4. Enter your server URL: `https://your-server.example.com/mcp`
5. Save — Claude will now have access to your remote machine's tools

## Connecting to Claude Code

Add this to your Claude Code MCP settings (`~/.claude.json` or project-level `.mcp.json`):

```json
{
  "mcpServers": {
    "my-remote-server": {
      "type": "url",
      "url": "https://your-server.example.com/mcp"
    }
  }
}
```

## Manual setup

If you prefer not to use the installer, or want to customize the setup:

### Standalone with Let's Encrypt

```bash
# Get a certificate
sudo certbot certonly --standalone -d your-server.example.com

# Run the server
SSL_CERT=/etc/letsencrypt/live/your-server.example.com/fullchain.pem \
SSL_KEY=/etc/letsencrypt/live/your-server.example.com/privkey.pem \
PORT=443 \
node server.js
```

### Behind nginx

Run the server on an internal port:

```bash
PORT=3098 node server.js
```

Add to your nginx config:

```nginx
server {
    listen 443 ssl;
    server_name your-server.example.com;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3098;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
```

### Behind Caddy

Caddy handles SSL automatically. Run the server on port 3098, then add to your Caddyfile:

```
your-server.example.com {
    reverse_proxy localhost:3098
}
```

## Environment variables

| Variable | Description | Default |
|----------|-------------|---------|
| `PORT` | Port to listen on | `443` (with SSL) / `3098` (without) |
| `SSL_CERT` | Path to SSL certificate (fullchain.pem) | _(none — runs HTTP)_ |
| `SSL_KEY` | Path to SSL private key (privkey.pem) | _(none — runs HTTP)_ |

See `.env.example` for a template.

## Security warnings

This server gives an AI agent shell access to your machine. Take precautions:

- **Create a dedicated user account** with limited permissions. Do not run this as root.
- **Firewall the port** so only trusted IPs can reach it.
- **Always use HTTPS.** Never expose this over plain HTTP on the internet. The installer handles this automatically.
- **Understand the risk**: any prompt injection or model mistake can run arbitrary commands on your server.
- **Network isolation**: consider running this on an internal network or behind a VPN for additional security.

## Health check

```bash
curl https://your-server.example.com/health
```

Returns JSON with server status and uptime.

## Systemd service management

If you used the installer, the service is managed via systemd:

```bash
# Check status
systemctl status mcp-remote-server

# View logs (live)
journalctl -u mcp-remote-server -f

# Restart
systemctl restart mcp-remote-server

# Stop
systemctl stop mcp-remote-server
```

## Troubleshooting

**Server won't start — "SSL certificate not found"**
Check that `SSL_CERT` and `SSL_KEY` point to valid files. If using Let's Encrypt, verify the cert exists at `/etc/letsencrypt/live/yourdomain/`.

**Port 443 permission denied**
Binding to ports below 1024 requires root or the `CAP_NET_BIND_SERVICE` capability. The systemd service file sets this automatically. For manual runs, use `sudo` or run on port 3098 behind a reverse proxy.

**certbot fails to obtain a certificate**
Make sure your domain's DNS A record points to your server's public IP, and that port 80 is open (certbot needs it for the HTTP challenge).

**Claude can't connect**
- Verify the server is running: `curl https://your-domain.com/health`
- Check firewall rules allow inbound traffic on port 443
- Ensure your SSL certificate is valid (not expired, matches the domain)

## License

MIT