MCP architecture / stdio vs SSE / Environment setup / Tool registration & permissions / launchd daemon / SSH tunnel / SSE multi-client / Production stability / FAQs
If you've been experimenting with Cursor, Claude Desktop, or OpenClaw recently, you've probably run into the same question: where should the MCP Server actually run? Keeping it on your daily driver exposes Shell permissions and the file system to the Agent; putting it on a remote Linux box means misaligned toolchains and no native macOS ecosystem. A cloud Mac mini sits exactly in between — Unix environment, snapshot isolation, and native macOS tooling all in one. This guide starts from the basics of stdio subprocesses and walks all the way to SSE multi-client, launchd daemons, and a configuration that can reliably run 24/7.
MCP Architecture: Host, Client, and Server
Before touching any keyboard, let's clarify what each role does:
- Host — The application that holds the user interface, such as Cursor, Claude Desktop, or OpenClaw. The Host manages the lifecycle of one or more Clients.
- Client — The protocol adapter layer running inside the Host. It discovers Servers, maintains connections, and forwards tool calls.
- Server — An independently running process that exposes Tools, Resources, and Prompts to the Host via a standardised protocol.
Host (Cursor)
└─ Client
└─ [stdio / SSE] ──── Server (MCP tool process)
Design principle: the Server process should run with least privilege — only register the tools the current task actually needs. Avoid the "omnipotent Agent" anti-pattern.
Transport Selection: stdio vs SSE vs WebSocket
| Transport | Typical Use Case | Cloud Mac Fit |
|---|---|---|
| stdio | Local subprocess, remote SSH command | ✅ Recommended: zero public ports, simplest setup |
| SSE | Browser clients, shared multi-Host | Needs reverse proxy + TLS + auth |
| WebSocket | Long-connection Gateway layer | Used by OpenClaw and similar Gateways |
The old approach of writing a bespoke REST glue layer for every integration has been replaced by MCP's unified tool discovery protocol — the Host fetches tools/list from the Server at startup, with no custom HTTP client needed per integration. This shift turns tool integration from "write from scratch every time" into "declare and use", letting a solo developer wire up a dozen MCP tools in a single afternoon.
Transport Layer Glossary
- stdio transport
- The Host launches the Server as a subprocess and exchanges JSON-RPC messages over stdin/stdout. The process exits when the Host exits — naturally isolated with no network exposure.
- SSE (Server-Sent Events)
- The Server listens on an HTTP port; Clients receive event pushes over a persistent connection. Supports multiple simultaneous Clients but requires network security configuration.
- Tool discovery (tools/list)
- The MCP handshake phase: the Host requests tools/list from the Server at startup, receiving tool names, parameter schemas, and descriptions, then calls tools on demand.
- HITL (Human In The Loop)
- A pattern where tool calls pause at sensitive operations to wait for human confirmation rather than letting the model decide autonomously.
Step 1: Prepare the Cloud Mac Environment
Choosing a Node
Latency and Region
Japan and Singapore nodes typically reach GitHub and npm with 20–60 ms latency, making them ideal for MCP tools that frequently pull packages or call external APIs. Hong Kong nodes offer lower latency to mainland China users.
Memory and Inference
If you plan to run MCP Server alongside a local small model (Ollama 7B-class), start with at least M4 + 16 GB. Apple Silicon's unified memory architecture handles CPU inference much more efficiently than comparable x86 machines.
Recommended Configuration Reference
| Scenario | Minimum | Recommended |
|---|---|---|
| Single MCP Server (tool calls only) | M4 + 8 GB | M4 + 8 GB |
| MCP + local 7B model | M4 + 16 GB | M4 + 24 GB |
| Multi-MCP + parallel CI builds | M4 + 24 GB | M4 Pro + 24 GB |
Initialising the Environment
SSH in and run in order:
# Install Homebrew (if not pre-installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install Node.js (MCP official SDK requires Node 18+)
brew install node@20
echo 'export PATH="/opt/homebrew/opt/node@20/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
# Verify
node -v # should output v20.x.x
npm -v
Note:
brew install nodeinstalls the latest version; usenvmto manage multiple versions if third-party MCP Servers require a specific release.
Step 2: Deploy the filesystem MCP Server (stdio mode)
# Start the filesystem Server, scoped to /Users/agent/workspace
npx -y @modelcontextprotocol/server-filesystem /Users/agent/workspace
Add the following to Cursor's MCP config (~/.cursor/mcp.json):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/agent/workspace"]
}
}
}
Key point: press Ctrl + C to stop a local stdio Server. Use launchd to manage the process lifecycle on a remote node (see Step 4).
Step 3: SSH Tunnel to Connect Cursor Remotely
# Map the remote port 3000 to local (SSE mode)
ssh -L 3000:127.0.0.1:3000 user@cloud-mac.zekvps.com
# SSH into the remote machine and start the Server (stdio mode)
ssh user@cloud-mac.zekvps.com "npx -y @modelcontextprotocol/server-filesystem /workspace"
For long-term stable deployments, consider Tailscale to create a Mesh VPN, replacing manual SSH port forwarding.
Step 4: launchd Daemon for 24/7 Uptime
Manually started processes disappear when the SSH session ends. Register the MCP Server as a launchd service for persistent operation.
Create ~/Library/LaunchAgents/com.zekvps.mcp-filesystem.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.zekvps.mcp-filesystem</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/opt/node@20/bin/npx</string>
<string>-y</string>
<string>@modelcontextprotocol/server-filesystem</string>
<string>/Users/agent/workspace</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/agent/.logs/mcp-filesystem.log</string>
<key>StandardErrorPath</key>
<string>/Users/agent/.logs/mcp-filesystem-err.log</string>
</dict>
</plist>
mkdir -p ~/.logs
launchctl load ~/Library/LaunchAgents/com.zekvps.mcp-filesystem.plist
launchctl start com.zekvps.mcp-filesystem
launchctl list | grep mcp
Deep dive: key differences between launchd and systemd
| Aspect | launchd (macOS) | systemd (Linux) |
|---|---|---|
| Config file format | XML plist | INI-style unit |
| User-level service path | ~/Library/LaunchAgents/ | ~/.config/systemd/user/ |
| Load command | launchctl load | systemctl --user enable |
| Log viewing | log stream / file | journalctl |
Never install systemd tooling on macOS to manage MCP processes — it is a Linux concept with no macOS support.
Step 5: SSE Mode for Shared Multi-Host Access
When multiple Hosts need the same Server (e.g., a shared database tool for a team), switch to SSE:
npm install -g @modelcontextprotocol/server-filesystem mcp-proxy
# Wrap the stdio Server and expose it as an SSE endpoint
mcp-proxy --port 3001 -- npx -y @modelcontextprotocol/server-filesystem /workspace
Cursor config for SSE:
{
"mcpServers": {
"filesystem-shared": {
"url": "http://cloud-mac.zekvps.com:3001/sse"
}
}
}
Security Boundaries and Permission Management
These four rules matter more than any framework choice:
- Minimum directory scope — scope
server-filesystem's path argument tightly; never pass~or/. - Inject secrets via environment variables — keep API keys and passwords out of plist files and
mcp.json; never commit them to Git. - Authenticate SSE endpoints — add a Bearer Token, reverse proxy (Caddy/nginx), and TLS; never expose
0.0.0.0directly. - Snapshot before major changes — restoring a snapshot beats rebuilding from scratch by an order of magnitude.
Reference: MCP's official security guidance recommends registering only the minimum tool set needed for the current task, and describing side-effects clearly in each tool's description for auditing.
Summary: Choosing Your Deployment Path
| Scenario | Recommended Deployment |
|---|---|
| Personal experiment, single Host | Local stdio (or SSH to cloud Mac) |
| 24/7 personal assistant, always-on | Cloud Mac + launchd daemon |
| Shared team tools, multiple Hosts | Cloud Mac + SSE + reverse proxy |
| High-security / compliance | Cloud Mac + Tailscale + audit logging |
See the OpenClaw column on this site for practical guides on co-deploying OpenClaw and MCP Server.
Isolate Your MCP Lab and Production on a Cloud Mac mini
Dedicated M4 node, rent by the day, SSH ready out of the box
Singapore · Japan · Korea · Hong Kong · US nodes available
If you are moving MCP or Agents from demo to daily use, a snapshot-ready cloud Mac node beats swapping frameworks again. View ZekVPS cloud Mac mini plans — Separate lab from daily driver for calmer deployments.