From 3e005bb9a289681e9b98690888ecd4cf650607fb Mon Sep 17 00:00:00 2001 From: chaodu-agent Date: Fri, 24 Jul 2026 21:33:22 -0400 Subject: [PATCH] =?UTF-8?q?feat(mcp):=20facade-only=20run=20mode=20?= =?UTF-8?q?=E2=80=94=20adapter-less=20config=20with=20[mcp]=20is=20valid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #1451. An adapter-less config with [mcp] present now runs just the OAB MCP Facade listener in the foreground (one entrypoint, config-driven) instead of bailing with 'no adapter configured'. The bail message now mentions the [mcp] option. Removes the openab-agent mcp-facade subcommand — serving surfaces do not belong on the coding-agent binary (nothing shipped depends on it; #1449 established the openab-side home). --- config.toml.example | 3 +++ openab-agent/src/main.rs | 17 ----------------- src/main.rs | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/config.toml.example b/config.toml.example index aa62c0a84..e06ac0c0d 100644 --- a/config.toml.example +++ b/config.toml.example @@ -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] diff --git a/openab-agent/src/main.rs b/openab-agent/src/main.rs index 04a5428b6..555e535fd 100644 --- a/openab-agent/src/main.rs +++ b/openab-agent/src/main.rs @@ -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)] @@ -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); - } - } } } diff --git a/src/main.rs b/src/main.rs index 63072b76d..c19962067 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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.)" ); }