Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ error_hold_ms = 2500
# ~/.openab/agent/mcp.json. Any coding CLI on this host (Kiro, Claude Code,
# Codex, ...) can connect to http://127.0.0.1:8848/mcp.
# Presence of [mcp] enables the listener; omit the section to disable.
# With no chat adapter configured, [mcp] alone is a valid config: openab
# runs in facade-only mode (serves just the MCP listener) — for
# coding-CLI-only hosts, dev loops, and CI runners (#1451).
# NOTE: the endpoint has no authentication — it must stay on loopback
# (non-loopback addresses are refused at startup).
# [mcp]
Expand Down
17 changes: 0 additions & 17 deletions openab-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ enum Commands {
#[command(subcommand)]
action: McpAction,
},
/// Serve the OAB MCP Facade over loopback Streamable HTTP: an inbound
/// MCP server exposing `search_capabilities` / `execute_capability`
/// backed by the configured downstream MCP servers (global + project
/// mcp.json). The OAB broker hosts the same facade in-process when
/// `[mcp]` is set in config.toml; this subcommand is the standalone way
/// to run it.
McpFacade {
/// Loopback address to listen on (non-loopback addresses are refused).
#[arg(long, default_value = "127.0.0.1:8848")]
listen: String,
},
}

#[derive(Subcommand)]
Expand Down Expand Up @@ -171,12 +160,6 @@ async fn main() {
}
}
},
Some(Commands::McpFacade { listen }) => {
if let Err(e) = mcp::facade::serve_http(&listen).await {
eprintln!("mcp-facade: {e:#}");
std::process::exit(1);
}
}
}
}

Expand Down
19 changes: 18 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,25 @@ async fn main() -> anyhow::Result<()> {
&& cfg.telegram.is_none()
&& !has_unified_platform(&cfg)
{
// Facade-only run mode (#1451): an adapter-less config with `[mcp]`
// present is a valid deployment — the broker serves just the OAB MCP
// Facade listener. One entrypoint, config-driven: hosts that only
// need the capability surface (coding-CLI-only users, dev loops, CI
// runners, agent hosts with no chat platform) run the same
// `openab run` with a two-line config instead of a chat token.
if let Some(mcp_cfg) = cfg.mcp.clone() {
tracing::info!(
listen = %mcp_cfg.listen,
"no chat adapter configured — running in facade-only mode ([mcp] present)"
);
// Foreground, not spawned: the facade IS the workload. A bind
// failure or server exit terminates the process (fail fast).
return openab_mcp::mcp::facade::serve_http(&mcp_cfg.listen)
.await
.map_err(|e| anyhow::anyhow!("OAB MCP facade exited: {e:#}"));
}
anyhow::bail!(
"no adapter configured — add [discord], [slack], [telegram], [wecom], [googlechat], or [gateway] to config, or set platform env vars (TELEGRAM_BOT_TOKEN, etc.)"
"no adapter configured — add [discord], [slack], [telegram], [wecom], [googlechat], or [gateway] to config (or [mcp] for facade-only mode), or set platform env vars (TELEGRAM_BOT_TOKEN, etc.)"
);
}

Expand Down
Loading