57 lines
2.5 KiB
Rust
57 lines
2.5 KiB
Rust
//! Builds a subagent's own filtered `--mcp-config`: only
|
|
//! `hyperhive.extraMcpServers` entries with `availableToSubagents = true`
|
|
//! (see `hive_agent_sock::extra_mcp::ExtraMcpServer::available_to_subagents`) ever reach
|
|
//! a subagent's claude invocation. Everything else — the built-in hyperhive
|
|
//! surface (todos/messaging), the automatically injected `bash` and `subagent`
|
|
//! entries — stays unreachable by construction: none of those default to
|
|
//! opted in, and the built-in surface isn't an `extraMcpServers` entry at
|
|
//! all, so there's no name for an operator to opt it in under even if they
|
|
//! wanted to.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
/// Filename the rendered config lives at, under [`crate::paths::harness_dir`].
|
|
const CONFIG_FILE: &str = "subagent-mcp-config.json";
|
|
|
|
/// Render the subagent-eligible extra-MCP servers to a `--mcp-config` file,
|
|
/// returning its path — or `None` when no entry opts in (or the render/write
|
|
/// fails), so [`hive_claude::Config::mcp_config`] stays unset and the
|
|
/// subagent gets literally zero MCP servers, the same default as before this
|
|
/// toggle existed. Re-rendered on every call (cheap: a filter plus a small
|
|
/// file write) rather than cached once at daemon startup, so a config change
|
|
/// takes effect on this subagent's next `start`/`continue` without needing
|
|
/// the daemon itself restarted.
|
|
#[must_use]
|
|
pub fn build() -> Option<PathBuf> {
|
|
let state_dir = crate::paths::state_dir();
|
|
let servers: serde_json::Map<String, serde_json::Value> =
|
|
hive_agent_sock::extra_mcp::load_extra_mcp()
|
|
.into_iter()
|
|
.filter(|(_, spec)| spec.available_to_subagents())
|
|
.map(|(name, spec)| (name, spec.to_json_entry(&state_dir)))
|
|
.collect();
|
|
if servers.is_empty() {
|
|
return None;
|
|
}
|
|
let body = serde_json::to_string_pretty(&serde_json::json!({ "mcpServers": servers }))
|
|
.unwrap_or_else(|_| "{}".into());
|
|
let dir = crate::paths::harness_dir();
|
|
if let Err(e) = std::fs::create_dir_all(&dir) {
|
|
tracing::warn!(
|
|
error = ?e,
|
|
dir = %dir.display(),
|
|
"subagent mcp-config: harness dir create failed; subagent gets zero extra MCP servers this turn",
|
|
);
|
|
return None;
|
|
}
|
|
let path = dir.join(CONFIG_FILE);
|
|
if let Err(e) = std::fs::write(&path, body) {
|
|
tracing::warn!(
|
|
error = ?e,
|
|
path = %path.display(),
|
|
"subagent mcp-config: write failed; subagent gets zero extra MCP servers this turn",
|
|
);
|
|
return None;
|
|
}
|
|
Some(path)
|
|
}
|