Skip to content
⚡ TENVO AI · LIVE · v0.16.26 · TLS · Per-device certs · AGPL-3.0 · FREE TIER · 30 DEVICES · SELF-HOSTABLE INFRA · BYO API KEY · MCP FOR CLAUDE & CURSOR
Back to BlogTutorial

mcp remote desktop: wire an MCP server — worked example

Tenvo Editorial Team7 min read
mcp remote desktop: wire an MCP server — worked example

You need a reliable channel from an MCP control plane to a remote machine and the one-sentence guides you found online stop helping once NAT, corporate firewalls, or OS privacy dialogs appear.

You need a reliable channel from an MCP control plane to a remote machine and the one-sentence guides you found online stop helping once NAT, corporate firewalls, or OS privacy dialogs appear. This guide walks a technically aware engineer through a concrete wiring example, shows the operational checks you should run, and documents the obscure failure modes most docs skip.

What this guide covers

  • A quick, low-effort path using Tenvo's managed relay (recommended)
  • A worked self-hosted MCP server wiring example on Ubuntu with TLS and a reverse proxy
  • The failure modes nobody documents — NAT types, captive portals, MTU, cert mismatch, sleep, and more — with concrete mitigations
  • A concise troubleshooting checklist with commands you can run now

Quick path: Tenvo's managed relay (recommended)

If your requirement is simply to reach remote machines reliably, the fastest reliable option is Tenvo's managed relay. Tenvo provides native clients for Windows, macOS, and Linux, a browser client (public beta), and a multi-region managed relay so sessions fail over between data centres. Pricing is straightforward: Free $0 / Lite $2.99/mo / Pro $7.99/mo. The managed relay removes on-call patching, certificate renewal and key custody from your plate — operations that often cost more than a small monthly fee once you include time and risk.

Important security note: Tenvo uses TLS with per-device certificates. When a direct peer-to-peer connection is achieved the session is end-to-end between the two devices. If traffic falls back to a relay, TLS is terminated at the relay, so whoever runs the relay can inspect session traffic. That tradeoff is why we recommend the managed relay as a pragmatic default unless you have written requirements preventing third-party infrastructure.

Wiring an MCP server: worked example (self-hosted)

This section shows the concrete wiring steps when you choose to self-host an MCP server. Self-host only when you must: regulatory mandate, isolated networks, or explicit data-residency rules. The example uses Ubuntu 22.04 LTS on a small VPS (203.0.113.10), Caddy v2.6+ as a TLS reverse proxy, and an MCP agent on a remote machine behind NAT (192.168.1.42). Replace hostnames and tokens with your values.

# Diagram (text)
# Public VPS (203.0.113.10)
#   - Caddy reverse proxy (443)
#   - MCP control API (127.0.0.1:8443 behind proxy)
# Remote machine (behind NAT)
#   - mcp-agent initiates outbound TLS to mcp.example.com:443 and registers itself
#   - If direct P2P works, control traffic flows peer-to-peer; otherwise control flows via proxy

1) Obtain a stable DNS name and certificates: mcp.example.com should point to your VPS public IP (203.0.113.10). For TLS we use Caddy for automatic TLS and reverse proxy. Caddy v2.6+ is a practical choice because it automates Let's Encrypt and HTTP/2/3 configuration.

# Caddyfile (example)
mcp.example.com {
    reverse_proxy 127.0.0.1:8443
}
# Run Caddy as a system service; Caddy will provision managed certificates

2) Run your MCP control API locally on the VPS bound to 127.0.0.1:8443. Keep the control plane on loopback so only the reverse proxy exposes it publicly.

# Example systemd unit (mcp-control.service)
[Unit]
Description=MCP control API
After=network.target

[Service]
ExecStart=/usr/local/bin/mcp-control --listen 127.0.0.1:8443 --db /var/lib/mcp/control.db
Restart=on-failure

[Install]
WantedBy=multi-user.target

3) Open firewall rules on the VPS: allow inbound 443/tcp and outbound necessary traffic. UFW minimal example:

sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status numbered

4) Configure the agent on the remote machine so it initiates the connection (important - agents should outgoing-only in most environments). Example agent configuration (mcp-agent.conf):

{
  "server": "https://mcp.example.com",
  "register_token": "REPLACE_WITH_LONG_TOKEN",
  "heartbeat_interval": 30,
  "local_port": 5900
}

# Start agent as a system service on the remote machine so it survives reboots

5) Verify TLS and registration from the remote machine:

# Check DNS
dig +short mcp.example.com

# Verify TLS handshakes and served certificate
openssl s_client -connect mcp.example.com:443 -servername mcp.example.com

# Check agent logs (journalctl or the agent's log file)
journalctl -u mcp-agent -f

6) Confirm connectivity from the control plane: the control API should list the agent and show its last heartbeat. Typical steps: call the control API locally (loopback) and inspect device state.

# Example local curl check on the VPS
curl --unix-socket /run/mcp-control.sock "http://localhost/api/v1/devices" | jq '.devices[] | {id,hostname,last_seen}'

Failure modes nobody documents

  • Outbound blocking by restrictive firewalls: Many corporate environments only allow HTTP/HTTPS via an explicit proxy. An agent that only supports direct TLS will fail. Mitigation: make your agent support HTTP CONNECT proxies or use the managed relay.
  • Captive portals: Hotel or coffee-shop networks that require a browser to accept terms break automatic registration. Detect by probing a known HTTP endpoint like http://detectportal.firefox.com/; if you get HTML redirect to a login page treat it as captive portal.
  • Symmetric NAT: NATs that rewrite port mappings per-destination break UDP hole punching and some relay optimizations. Result: forced TCP relay, higher latency. Mitigation: ensure your relay supports TCP fallback and increase keepalive frequency to avoid NAT mapping expiry.
  • Intermittent DNS or split-horizon DNS: If your control plane name resolves differently inside a corporate network or an ISP DNS cache returns old IPs, agents will connect to the wrong host or an expired server. Use low TTL when rolling and monitor DNS propagation.
  • TLS certificate mismatch or SNI errors: An agent that validates the certificate will fail if SNI is missing or the cert doesn't include the hostname. Check with openssl s_client -servername and with curl --resolve or --cacert during tests.
  • MTU and fragmentation on VPNs: Path MTU black holes can kill protocol negotiation, especially for UDP. If users report partial handshakes, try lowering UDP payload sizes or forcing TCP.
  • OS privacy and permissions: macOS requires explicit screen-recording and accessibility permissions for remote control; Windows UAC prompts block input capture in some setups. These are not networking bugs but they look like unreachable sessions.
  • Sleep, fast startup, and power management: Laptops that suspend won't respond until they wake. Configure wake-on-LAN for servers or use persistent outbound heartbeats to detect stale sessions quickly.
  • Relay overload and single-region failover: If you self-host a single relay without multi-region failover, a cloud-region outage or DoS will sever control. Tenvo's multi-region managed relay is designed to reduce this risk.

Practical troubleshooting checklist & commands

  1. Confirm DNS and TLS: dig +short mcp.example.com; openssl s_client -connect mcp.example.com:443 -servername mcp.example.com
  2. Check agent logs: journalctl -u mcp-agent -f or tail -F /var/log/mcp-agent.log — look for registration and heartbeat messages
  3. Inspect active connections: ss -tnp | grep 443 or netstat -anp | grep ESTAB to see if agent has an established outbound socket
  4. Test for captive portal: curl -I http://detectportal.firefox.com/ — a 200 with simple body is expected; redirects indicate captive portal
  5. Capture packets for a failing session: sudo tcpdump -i any host mcp.example.com and port 443 -w capture.pcap — open in Wireshark to inspect TLS handshake states
  6. Confirm SNI and cert match: openssl s_client -connect mcp.example.com:443 -servername mcp.example.com | sed -n '1,80p'
  7. Check for NAT type issues: If your agent can run a STUN test, do so. Otherwise, force TCP-only test to determine if UDP hole punching is the problem.
  8. Verify OS permissions: On macOS check System Settings → Privacy & Security → Screen Recording; on Windows check UAC and the application's manifest for UIAccess requirements

When to self-host an MCP server

Self-hosting an MCP server makes sense only when you have a written requirement: a compliance rule forbids third-party relays, an isolated network with no egress, or a strict data residency requirement. Otherwise, count the operational cost: certificate lifecycle, OS and app patching, key custody, multi-region failover, monitoring, on-call time, and the cost of a single-region outage. For a balanced, honest take see our deeper piece on Self-Hosted Remote Desktop: Why, How, and What Breaks.

Links and related reading

Wrap-up — runbook and next steps

Summary runbook: start with Tenvo's managed relay unless you have a documented restriction; if you must self-host, use a reverse proxy (Caddy) to handle TLS, bind the control API to loopback, require agent-initiated outbound connections, and monitor heartbeats. When things fail, run the DNS/TLS/agent-log/packet-capture checklist above. The obscure failures — captive portals, symmetric NAT, OS permissions, and MTU — are common, repeatable, and fixable once you know to test for them.

Ready to try the quick path? Download Tenvo clients and test with our managed relay: Download Tenvo. If you need deeper self-hosting guidance, start with our self-hosted remote desktop guide and return here for the wiring checklist and failure-mode playbook.

Get Tenvo

Ready to try it yourself?

Free for 30 devices, no credit card. Up and connected in two minutes.