Runtime architecture
Hyperbolic Gateway has one desktop process that owns the browser and two optional stdio server processes that expose it to agent clients.
Agent / MCP client
| stdio JSON-RPC
+-- hb-browser (bin/mcp-server.cjs) -- HTTP --> 127.0.0.1:4111
| |
+-- hb-rest (bin/wrap-server.cjs) -- HTTP --> /wrap/*
|
Electron main process
- BrowserChassis
- WebContentsView tabs
- primitives and input
- Cortex and vaults
- wrapper store and secrets
|
visible Chromium
Electron app
The main process owns the window, browser tabs, HUD, local database, downloads, and files. The browser is a real visible Chromium session with persistent cookies and ordinary navigation state.
The bridge binds to 127.0.0.1 on port 4111 by default. HB_BRIDGE_PORT
changes the port. Two app instances cannot share one port; the second reports
EADDRINUSE.
hb-browser
Each MCP client starts its own copy of bin/mcp-server.cjs. It speaks
JSON-RPC over stdin/stdout and forwards tool calls to the bridge. It does not
open a browser itself and it does not store durable state.
The server name is hb-browser; kuang is the legacy alias. The process
uses HB_BRIDGE_URL (legacy KUANG_BRIDGE_URL) and never writes logs to
stdout, because stdout is the protocol channel.
hb-rest
bin/wrap-server.cjs is a separate MCP server with its own configuration.
It forwards /wrap/* calls to the bridge using a rotating bearer token read
from HB_WRAP_TOKEN_FILE.
The wrapper store, secret store, executor, recipe renderer, and audit log all live in the Electron main process. The MCP process sees wrapper metadata and rendered results, never credential values.
Request flow
For a browser call:
- The agent sends a
tools/callrequest tohb-browser. - The server validates and normalises arguments.
- It sends an HTTP request to the bridge.
- The main process executes the browser primitive.
- The result is formatted as text or an image block and returned over stdio.
For a REST wrapper:
- The agent calls
wrap_runor a generatedwrap_<id>. hb-restreads the bridge token and posts to/wrap/run.- The executor validates flat arguments, builds the request, applies the outbound policy, attaches a host-bound secret if allowed, fetches, and renders the recipe.
- The result returns as Markdown, JSON records, or both.
Storage
| Location | Contents |
|---|---|
<userData>/bin/ |
MCP binaries copied by an installed build. |
<userData>/wrap/wrappers/ |
One JSON file per wrapper, written atomically. |
<userData>/wrap/secrets.json |
Secret metadata and ciphertext only. |
<userData>/wrap/audit.jsonl |
Redacted outbound-call audit rows. |
<userData>/wrap/token |
Rotating bridge token, owner-only permissions. |
<data>/logs/ |
MCP, bridge, and app logs. |
Design boundaries
packages/recipeis pure: no network, filesystem, Electron, or MCP.hb-restis stateless. The main process owns state and credentials.- The browser MCP server does not own wrapper credentials.
- The bridge is local-only. It is a control surface, not a remote API gateway.
See Security model for the trust boundaries and known limits.