Skip to main content
Glama
gitayg

HaiveControl MCP Server

by gitayg

HaiveControl

A hive of your machines, one AI mind. Self-hosted, LAN-first remote control with a built-in MCP interface — so an AI (Claude, etc.) can see the screen, run commands, and move files across a whole fleet of devices from one place.

license: AGPL-3.0

A tiny single-file tool for your own machines (Windows, macOS, Linux). One binary runs on each target: it streams the full screen, accepts mouse + keyboard control, runs shell commands, and transfers files over HTTPS. Drive it from any browser, a CLI, or an MCP-enabled AI — nothing to install on the viewing side.

View + control + a remote command box. LAN-only, hub model: the Mac runs a small hub with an ID; you launch the Windows exe with just that ID; it finds the Mac over Bonjour and registers itself. This is a real remote-admin agent — see Security below.

How it works

  Mac:      HaiveHub                 → prints  "Mac ID: itays-macbook-pro"
  Windows:  HaiveControl.exe itays-macbook-pro
                 └─ finds the Mac by that id (Bonjour), registers itself,
                    then serves screen + control + shell on port 8765
  Mac:      open the hub dashboard  → the Windows box is listed → click to view

The only thing you configure on Windows is one argument: the Mac's ID.

Related MCP server: Systems Manager

Built in Rust

HaiveControl is a Rust workspace producing four small, dependency-free binaries:

Binary

Role

~size

HaiveControl

agent (runs on each device)

5 MB

HaiveHub

hub (runs on the Mac)

3 MB

haivectl

CLI (Mac)

5 MB

haive-mcp

MCP server (Mac)

6 MB

Build from source: cargo build --release → binaries land in target/release/.

CI builds all three platforms. .github/workflows/build.yml runs a Windows + macOS + Linux matrix (cargo build --release) and attaches all four binaries per OS to the release:

  • Tag a release: git tag v1.0.0 && git push --tags → e.g. HaiveControl-windows.exe, HaiveControl-macos, HaiveControl-linux, plus the HaiveHub-*, haivectl-*, haive-mcp-* sets.

  • Or run the build workflow manually (workflow_dispatch) → download from Artifacts.

Nothing to install to run them — they're static native binaries.

Platform notes (runtime)

  • Windows — works out of the box. The C runtime is statically linked (+crt-static), so no Visual C++ Redistributable is required (no VCRUNTIME140.dll).

  • macOS — the agent needs Screen Recording and Accessibility permission (System Settings → Privacy & Security). Unsigned binary: right-click → Open the first time to clear Gatekeeper.

  • Linux — needs an X11 session (Wayland unsupported by the capture/input crates). Build deps: libxdo-dev libxcb1-dev libx11-dev libxtst-dev.

Step 1 — start the hub on the Mac

Run HaiveHub (./HaiveHub-macos). It prints your Mac ID and a dashboard URL, e.g.:

Mac ID:  itays-macbook-pro
Dashboard: http://localhost:8770/
On Windows run:  HaiveControl.exe itays-macbook-pro

Keep it running. Both machines must be on the same LAN.

Step 2 — run the agent on the target

The hub hosts the binaries, so the target downloads and runs in one line — no manual copy. The dashboard shows a ready-made, per-OS command with a copy button. It downloads the file as airm and registers it. For example:

# Windows (PowerShell or cmd) — works in both
curl.exe -L -o airm.exe http://MAC_IP:8770/bin/HaiveControl-windows.exe
.\airm.exe MAC_IP:8770 --id itays-macbook-pro
# macOS / Linux
curl -L -o airm http://MAC_IP:8770/bin/HaiveControl-macos && chmod +x airm
./airm MAC_IP:8770 --id itays-macbook-pro

The target can be given by direct IP (MAC_IP:8770), by Mac ID (Bonjour --id), or both (IP first, Bonjour fallback). Append a password as a final argument to require auth. After registering, the agent prints ready. The first run triggers a firewall prompt — allow it on private networks.

Staying current

The agent auto-checks the hub for a newer build every 2 minutes and self-updates in place. You can also push an update on demand from the dashboard (Update) or MCP (update_agent) — the agent replaces its own executable and relaunches with the same arguments.

Lifetime modes

Pick how long the agent sticks around (default = one-time):

Mode

Flag

Behaviour

One-time

(none)

Runs until you close it. Nothing installed.

Persistent

--persist

Installs autostart so it comes back on every boot.

Timed

--ttl MIN

Runs for MIN minutes, then exits and removes any autostart.

HaiveControl.exe mymac secret --persist       :: survives reboot
HaiveControl.exe mymac secret --ttl 30         :: self-dissolves after 30 min
HaiveControl.exe --uninstall                   :: remove autostart, exit

Autostart uses the standard, visible mechanism per OS — Windows HKCU\…\Run, a macOS LaunchAgent (~/Library/LaunchAgents/com.haive.agent.plist), or a Linux XDG autostart .desktop. Nothing hidden; --uninstall (or deleting that entry) removes it. "Dissolve" stops the process and clears autostart — it does not delete the binary (self-deleting executables are a malware pattern, intentionally avoided).

Step 3 — connect from the Mac

Open the hub dashboard (http://localhost:8770/). The Windows machine appears in the list — click it. The dashboard link uses https (see below). If a password was set, the browser shows a login prompt (username can be anything, password = the one you passed); otherwise the live screen opens directly. No IP to look up.

Password can also come from the SCREEN_PW env var — the 2nd CLI argument just overrides it, so it's easy to bake into a Startup shortcut.

HTTPS (on by default)

The agent serves over TLS using a self-signed certificate it generates on first run (stored in ~/.haive/ on the Windows box, so it's stable across restarts). Traffic — screen, keystrokes, password, command output — is encrypted.

Because the cert is self-signed, the first time you connect the browser shows a "Not private / not secure" warning. Two options:

  • Quick: click Advanced → Proceed. You're now on an encrypted connection.

  • No more warnings: copy ~/.haive/cert.pem from the Windows box to the Mac, open it in Keychain Access, and set it to Always Trust. The lock goes green for that machine.

Set SCREEN_TLS=0 to fall back to plain HTTP if you'd rather not deal with the cert.

Using it — the hub dashboard

The dashboard is a single-page console: a device sidebar on the left, a stage on the right. Pick a device and everything happens in place — no new tabs. The sidebar polls every few seconds so status dots (online / idle / stale) and last-seen stay live without reloading (an active stream keeps playing).

Per selected device you get its details (OS, CPU, memory, user, IPs, cameras, mics), live CPU-load and free-RAM meters (re-sampled every cycle), and an action bar that renders results in the stage viewport:

  • ● Live screen — the full screen streams live (MJPEG).

  • ● Cam live — live webcam video. A camera picker chooses which camera; the same picker feeds Camera shot.

  • Screenshot / Camera shot — a single fresh frame.

  • Run… — enter a single command; stdout/stderr print to the inline console.

  • Shell — a full interactive terminal (xterm.js over a real PTY): colors, Ctrl-C, arrows, tab-completion, top/vim, live resize.

  • Get file / Put file — a remote file browser to download or upload.

  • Update — hot-update this agent to the hub's latest build.

  • Dissolve — stop the agent and remove its autostart (does not delete the binary).

Uploads land in SCREEN_SHARE (or the user's home dir if unset); with SCREEN_SHARE set, browsing/downloads are confined to that folder (.. is blocked).

Run commands from the Mac (API + CLI)

Everything the browser does is a plain HTTP API on the agent, so you can drive a device from a script. Two ways:

haivectl (recommended) — resolves the device through the hub by name, so you never type its IP:

haivectl list                          # list registered devices
haivectl exec mymac "ipconfig /all"    # run a command, print output
haivectl get  mymac C:\logs\app.log    # download a file
haivectl put  mymac ./patch.zip C:\tmp # upload a file

Global flags come before the subcommand: --hub (default http://localhost:8770), --password (if the agent set one), --cafile (agent cert.pem to verify TLS).

Raw API (talk to the agent directly; -k because the cert is self-signed):

curl -sk -u :SECRET https://DEVICE_IP:8765/exec \
  -H 'Content-Type: application/json' -d '{"cmd":"whoami"}'

Returns {"ok":true,"code":0,"stdout":"…","stderr":"…"}. Other endpoints: GET /download?path=…, POST /upload (multipart file, optional dir).

Use it as an MCP server (drive devices from an AI)

The haive-mcp binary wraps the same API as MCP tools, so an AI client (Claude Code, Claude Desktop, etc.) can operate a device by name. Tools exposed:

  • list_devices() — registered devices, with full details (OS, CPU, memory, logged-in user, IPs, cameras, microphones, last-seen)

  • screenshot(device) — the current screen as an image

  • camera_snapshot(device, index?) — a still from a connected webcam (pick which with index)

  • run_command(device, command) — run a shell command, get output

  • click(device, x, y) / type_text(device, text) / press_key(device, key) — drive mouse + keyboard

  • download_file(device, remote_path, save_as?) / upload_file(device, local_path, remote_dir?)

  • update_agent(device) — hot-update the agent to the hub's latest build

  • dissolve_agent(device) — stop the agent and remove its autostart

Live video (screen and camera) streams as MJPEG in the browser dashboard; it isn't an MCP tool because a stream isn't a single tool response — use screenshot / camera_snapshot for AI-driven stills.

One MCP server, many devices

The hub tracks every registered agent, so a single haive-mcp controls them all — just run the agent on each device with the same Mac ID. They each register and you target them by name: run_command("linux-box", …), screenshot("macmini"). Give each a clear label with --name (or SCREEN_NAME) so they're easy to tell apart:

HaiveControl.exe mymac secret --name reception-pc

Runs on the Mac next to the hub. Register the binary:

claude mcp add haive -- /full/path/to/haive-mcp

The MCP drives devices entirely through the hub's /m API (it never talks to an agent directly), so the same setup works for LAN and cloud/relay devices. Config via env (set in your MCP client, or export before launch):

  • HAIVE_HUB — hub base URL (default http://localhost:8770; a cloud hub's https://…).

  • HIVE_MCP_TOKEN — token for the hub's /m API (must match the hub's MCP_TOKEN).

  • HIVE_OWNER — the owner id to act as, so a multi-user hub scopes tools to your devices.

  • HAIVE_CAFILE — optional PEM to verify a self-signed hub cert.

Then just ask: "take a screenshot of mymac", "run ipconfig on mymac", "download C:\logs\app.log from mymac".

Against a cloud hub (crane.glick.run): set MCP_TOKEN on the hub and add /m to auth_bypass_paths (a headless MCP can't pass SSO — same reason as the agent). Then point the local MCP at it with HAIVE_HUB=https://<app-url>, HIVE_MCP_TOKEN=<token>, HIVE_OWNER=<your-email>. The MCP runs on your Mac; only its HTTP calls to the hub cross the network.

Reverse-tunnel relay (control beyond the LAN)

The default model is pull: the hub reaches into each device at its IP. That only works when the hub can route to the device — same LAN. To control devices across NAT or from a cloud-hosted hub, run the agent in relay mode: it dials out to the hub and holds the connection, and the hub drives it back down that channel. The device never needs a public address.

HaiveControl <mac-id> --relay https://your-hub.example.com     # cloud hub
HaiveControl <mac-id> --relay http://192.168.1.10:8770         # or any reachable hub
  • The tunnel is HTTP long-poll on the hub's normal port (/relay/hello, /relay/poll, /relay/reply) — no extra port, no WebSocket — so it rides a single HTTPS endpoint. Every action (screenshot, live video, shell, files, update, dissolve) works over it: the agent satisfies each request by calling its own loopback server and streams the result back.

  • Relay devices show up in the dashboard like any other, tagged relay, with live CPU/RAM.

Deploy the hub on AppCrane (crane.glick.run)

The repo ships a Dockerfile + deployhub.json that build the hub from source and bake in the current agent binaries (served at /bin/*). The hub reads PORT, exposes /api/health{status, version}, and — when HUB_PUBLIC_URL is set — shows relay-mode install commands in the dashboard. Recipe:

A headless agent can't pass SSO (no browser, no login), so the agent-facing paths must be SSO-bypassed — and the hub then authenticates the agent itself with a shared token.

  1. Create the app from this repo (custom Dockerfile is auto-detected).

  2. Set env / secrets:

    • HUB_PUBLIC_URL=https://<your-app-url> — makes the dashboard show relay-mode install commands (add a custom domain for a cleaner product).

    • RELAY_TOKEN=<a long random secret>the agent's credential; it replaces SSO on /relay, and the dashboard bakes it into the shown install command.

  3. Bypass SSO on the agent-facing paths (auth_bypass_paths=["/relay","/bin","/m"]; add /m only if you use the MCP) so devices can reach the tunnel + downloads and long-lived connections aren't buffered or cut — on AppCrane this sets flush_interval -1 and zero read/write timeouts. Keep /x/* behind SSO — that's the device-control surface, admin-only. TLS is terminated at the platform edge, so the tunnel is encrypted even though it's plain HTTP inside. /bin serves only public binaries, so it needs no token.

  4. Deploy, then on each device run the relay command the dashboard shows (./airm --relay https://<your-app-url> --relay-token <token> --name <device>).

Relay auth: with RELAY_TOKEN set, every /relay/* call must carry ?tok=<token> — the agent sends it (--relay-token or HIVE_RELAY_TOKEN); wrong/absent → 401. Unset = open (trusted LAN / dev). Query-string tokens on bypass paths aren't logged by the proxy.

Per-user devices (multi-user hub). When AppCrane forwards the authenticated user (X-AppCrane-User-Email), the hub scopes everything to that user: the device list (/agents + dashboard) shows only devices they own, and device actions (/x/*) are refused (403) on devices they don't. Ownership comes from the owner a device registered with — the dashboard bakes --owner <you> into the install command it shows, so a device a user enrolls is automatically theirs. No user header (LAN/dev) = full access, as before.

The owner is self-asserted by the agent, so it's a visibility/soft boundary — a holder of the shared RELAY_TOKEN could plant a device under another owner. Per-user relay tokens (token → identity) would make it a hard boundary; a reasonable next step.

Config (environment variables)

Var

Default

Meaning

SCREEN_PW

(empty)

Password. Empty = open (LAN mode); set to require auth

SCREEN_PORT

8765

Listen port

SCREEN_FPS

10

Frames per second

SCREEN_QUALITY

60

JPEG quality 1–95

SCREEN_MAXW

1600

Downscale frames wider than this (px)

SCREEN_MONITOR

0

0 = all monitors, 1 = primary, 2 = second, …

SCREEN_EXEC

1

Set 0 to disable the remote command box

SCREEN_TLS

1

Set 0 to serve plain HTTP instead of HTTPS

SCREEN_SHARE

(empty)

Confine file transfer to this folder; empty = whole filesystem

SCREEN_NAME

hostname

Friendly device label shown in the hub (also --name)

Unattended / start at login

Put a shortcut to HaiveControl.exe in the Startup folder (shell:startup), or create a Task Scheduler task "At log on". To pass a password, point the shortcut at a small .bat that does set SCREEN_PW=… & HaiveControl.exe.

Security — read this

  • LAN-only, open by default. With no SCREEN_PW, anyone on the same LAN who reaches port 8765 gets the screen, control, and the shell. That's fine on a trusted home network; on an untrusted/shared LAN, set SCREEN_PW and/or SCREEN_EXEC=0. Don't port-forward this to the internet.

  • /exec is a full remote shell on the Windows box, running as you. Set SCREEN_EXEC=0 to disable it if you only want view + control.

  • Plain HTTP — traffic is unencrypted. Acceptable on a trusted LAN, which is the intended use here.

  • Browser eats some shortcuts. Combos like Ctrl+W / Ctrl+T are handled by your Mac browser before reaching the remote. Use the command box for those cases.

  • Intended for your own devices. Don't deploy it to watch someone without consent.

Layout (Rust workspace)

  • crates/agentHaiveControl — the agent (Windows/macOS/Linux): screen capture, /frame, /stream (live MJPEG), /camera + /camstream (webcam), /input, /exec, /shell/* (interactive PTY shell), /upload, /download, /list, /update, /dissolve; registers to the hub and reports full sysinfo + live CPU/RAM. Modules: capture (xcap + nokhwa), input (enigo), shell (portable-pty), tls (rcgen), discovery (mdns-sd, self-update), relay (outbound long-poll tunnel), http (which also runs a loopback twin the relay self-calls), persistence.

  • crates/hubHaiveHub — the Mac hub: Bonjour advertise, /register, /agents, the single-page dashboard (with a bundled xterm.js terminal at /assets/*), hosts the agent binaries (/bin/*), proxies device actions (/x/*, incl. live-stream passthrough), and terminates the reverse tunnel (/relay/*, see relay.rs).

  • crates/clihaivectl — Mac CLI: list / exec / get / put by device name.

  • crates/mcphaive-mcp — Mac MCP server: list_devices / screenshot / run_command / download_file / upload_file tools (rmcp).

  • .github/workflows/build.ymlcargo build --release matrix (Windows/macOS/Linux).

License

HaiveControl is free software licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later) — see LICENSE. In short: you may use, modify, and redistribute it, but if you run a modified version as a network service, you must offer that service's users the corresponding source. It comes with no warranty.

Intended use

For administering your own devices, or devices you're authorized to manage with the user's knowledge. It's deliberately visible — the autostart entry is standard and removable, and it does not hide its process or erase its traces. Don't deploy it to surveil people without consent.

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
6Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gitayg/HaiveControl'

If you have feedback or need assistance with the MCP directory API, please join our Discord server