-
Notifications
You must be signed in to change notification settings - Fork 1
Shared Daemon
By default, all hyperdb-mcp clients on a machine share one hyperd
process per user, managed by a small background daemon. Multiple AI clients
(Claude Code, Cursor, VS Code Copilot) then talk to the same engine and the
same persistent databases instead of each spawning their own hyperd. Pass
--no-daemon to opt out and get a private per-session hyperd (legacy
behavior).
This page explains how the daemon is discovered, how it stays out of your way, and the knobs for the rare cases where you need to intervene.
The daemon owns the hyperd process and advertises how to reach it in a small
JSON file:
~/.hyperdb/daemon.json # discovery file (override dir with HYPERDB_STATE_DIR)
~/.hyperdb/logs/ # hyperd logs
Two ports, two owners — don't conflate them:
| Field | Owned by | Purpose |
|---|---|---|
hyperd_endpoint |
hyperd |
The libpq endpoint your queries connect to. |
health_port |
the Rust daemon wrapper | Single-instance lock and a control channel (PING / HEARTBEAT / STOP / STATUS). |
The health port doubles as the lock: binding it succeeds for exactly one process per user, which is how "single instance" is enforced cross-platform.
A starting client resolves the daemon in this order:
-
Read
daemon.jsonand verify the daemon is really alive (see identity check below). If it checks out, connect. - Scan the port range if the file is missing or stale: probe ports upward from the base, looking for a live daemon.
- Spawn a new daemon on the first free port if none is found.
A client doesn't trust a port merely because something accepts a TCP connection
there. It sends PING and requires the reply to be exactly:
PONG hyperdb-mcp <version>
An unrelated process occupying the port (it answers TCP but not this protocol)
is classified as camped and skipped. A stale daemon.json pointing at a
dead or foreign port is detected and removed, and the client moves on to scan or
spawn. This prevents a client from ever mistaking some other service for the
daemon.
-
Default: scan upward from 7485 (16 ports:
7485..=7500) and use the first free one.7485was chosen deliberately — the older default7484collides withhyperd's conventional gRPC port, which is exactly the kind of process that would otherwise be mistaken for a daemon. -
Pin an exact port: set
HYPERDB_DAEMON_PORT=<port>. This disables scanning — the daemon uses exactly that port, and clients look only there.
By default the daemon — and the hyperd it owns — stay running once
started. Keeping hyperd warm means the next tool call connects instantly
instead of triggering a cold start and the "hyper is restarting, please retry"
round-trip.
If you want the daemon to shut itself down after a period of inactivity (for example on CI), opt in:
hyperdb-mcp daemon --idle-timeout 1800 # shut down after 30 min idle
# or
export HYPERDB_DAEMON_IDLE_TIMEOUT=1800 # same, via envWith neither set, the daemon only stops on an explicit stop, an OS signal, a
newer-version takeover (below), or repeated hyperd startup failures (3 within
60 seconds, which trips a safety shutdown so a broken binary doesn't spin
forever).
When you upgrade hyperdb-mcp, the next client built from a strictly newer
version automatically takes over: it stops the old daemon (which also stops the
old hyperd) and starts a fresh one on the same port. You don't have to
manually kill anything — the upgrade takes effect on the next client start.
Equal or older versions reuse the running daemon and never downgrade-kill it.
Note that the version compared is the crate's semantic version, so two local
builds of the same version (e.g. two dev builds of 0.4.0) are considered
equal and won't take over each other — use hyperdb-mcp daemon stop to force a
replacement in that case.
The daemon is normally invisible. For diagnostics:
hyperdb-mcp daemon status # PID, hyperd endpoint, health port, started_at, version
hyperdb-mcp daemon stop # gracefully stop the running daemon
hyperdb-mcp daemon # run as a daemon explicitly (rarely needed)status and stop locate the running daemon automatically (read daemon.json,
then scan), so they work even if the daemon landed on a non-default port. Pass
--port <PORT> to target a specific port explicitly.
The daemon detects a crashed hyperd (process exited) within ~5 seconds and
restarts it, updating daemon.json with the new endpoint; clients reconnect
transparently. A client that notices the failure first can fast-path the signal
so the restart doesn't wait for the polling tick.
A hung-but-alive hyperd (still listening, but not answering queries) is the
one case the daemon can't auto-detect. Because the daemon now stays resident by
default, there's no idle timeout to eventually reap it. Recovery is:
hyperdb-mcp daemon stop # then let the next client spawn a fresh one| Variable | Effect |
|---|---|
HYPERDB_STATE_DIR |
Directory for daemon.json + logs (default ~/.hyperdb/). |
HYPERDB_DAEMON_PORT |
Pin the health/lock port exactly (default: scan from 7485). |
HYPERDB_DAEMON_IDLE_TIMEOUT |
Opt into idle shutdown after N seconds (default: stay resident). |
{ "pid": 12345, "hyperd_endpoint": "127.0.0.1:54321", // where SQL goes (the database) "health_port": 7485, // the daemon's control/lock port "started_at": "2026-06-06T10:20:35Z", "version": "0.4.0" }