feat(#2038): wire persistent hive-mcp-http daemon behind hyperhive.mcp.httpPort
This commit is contained in:
parent
4a82ed02cf
commit
3c10b00460
1 changed files with 62 additions and 0 deletions
|
|
@ -828,6 +828,34 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
options.hyperhive.mcp.httpPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
example = 8790;
|
||||
description = ''
|
||||
Serve the built-in hyperhive MCP surface as a persistent
|
||||
streamable-http daemon on this loopback port instead of the
|
||||
default per-turn stdio child.
|
||||
|
||||
When null (the default) claude spawns a fresh `hive … mcp` stdio
|
||||
subprocess every turn — the shape that carries the per-turn MCP
|
||||
re-registration race (a resumed turn can emit its first tool call
|
||||
before that turn's async `initialize`/`tools-list` completes,
|
||||
stranding the agent with `No such tool`). When set, a long-lived
|
||||
`hive-mcp-http` systemd unit runs `hive mcp --http 127.0.0.1:<port>`
|
||||
and `render_claude_config` points claude at the stable
|
||||
`http://127.0.0.1:<port>/mcp` URL, which survives the per-turn
|
||||
claude re-spawn (and a host-side hive-c0re restart — each tool call
|
||||
dials the control socket fresh). Extra MCP servers (matrix/bash)
|
||||
stay stdio bridges regardless.
|
||||
|
||||
Bound loopback-only; the rmcp streamable-http transport's default
|
||||
`allowed_hosts` (`localhost` / `127.0.0.1` / `::1`) rejects Host
|
||||
headers from anywhere else, so no auth token is required for a
|
||||
container-local endpoint.
|
||||
'';
|
||||
};
|
||||
|
||||
config = {
|
||||
warnings = lib.optional (config.hyperhive.allowedBashPatterns != [ ]) ''
|
||||
hyperhive.allowedBashPatterns is deprecated and has no effect.
|
||||
|
|
@ -1709,6 +1737,33 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
# Persistent streamable-http MCP daemon for the built-in hyperhive
|
||||
# surface. Only wired when `hyperhive.mcp.httpPort` is set; otherwise
|
||||
# the surface stays the default per-turn stdio child (rendered by
|
||||
# `render_claude_config`). Long-lived so claude reconnects to the
|
||||
# stable URL each turn instead of respawning + re-registering a stdio
|
||||
# subprocess (the per-turn MCP registration race). It dials the
|
||||
# control socket (`/run/hive/mcp.sock`, the `hive` binary default)
|
||||
# fresh on every tool call, so a host-side hive-c0re restart is
|
||||
# transparent. `before = hive-ag3nt` so the URL is already listening
|
||||
# by the time the harness renders the first turn's config; the
|
||||
# harness/claude also reconnect on their own, so ordering is a
|
||||
# latency nicety not a hard correctness dep.
|
||||
systemd.services.hive-mcp-http = lib.mkIf (config.hyperhive.mcp.httpPort != null) {
|
||||
description = "persistent streamable-http MCP daemon for the hyperhive surface";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "hive-ag3nt.service" ];
|
||||
environment.RUST_LOG = "info";
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.hyperhive}/bin/hive mcp --http 127.0.0.1:${toString config.hyperhive.mcp.httpPort}";
|
||||
SyslogIdentifier = "hive-mcp-http";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 3;
|
||||
User = userName;
|
||||
Group = userName;
|
||||
};
|
||||
};
|
||||
|
||||
# Re-fire the daemon when the matrix token appears (hive-c0re
|
||||
# provisions it after agent containers come up). Without this
|
||||
# the daemon would exit 0 silently on first boot and the MCP
|
||||
|
|
@ -1802,6 +1857,13 @@ in
|
|||
# bind-mounts and gateway upstream config stay in sync.
|
||||
HIVE_WEB_SOCKET = "/run/hive-agent/${userName}/web.sock";
|
||||
}
|
||||
// lib.optionalAttrs (config.hyperhive.mcp.httpPort != null) {
|
||||
# Presence tells `render_claude_config` to point claude at the
|
||||
# persistent `hive-mcp-http` daemon's loopback URL instead of a
|
||||
# per-turn stdio child. Kept in sync with the `hive-mcp-http`
|
||||
# unit's `--http` port above via the same option.
|
||||
HYPERHIVE_MCP_HTTP_PORT = toString config.hyperhive.mcp.httpPort;
|
||||
}
|
||||
// lib.optionalAttrs config.hyperhive.gui.enable {
|
||||
# Tells the harness which fixed VNC port weston bound, and (by
|
||||
# its presence) that gui is enabled — the harness `/screen/ws`
|
||||
|
|
|
|||
Loading…
Reference in a new issue