diff --git a/crates/rhema-claw/Cargo.toml b/crates/rhema-claw/Cargo.toml index 4cb9549..8bfdd44 100644 --- a/crates/rhema-claw/Cargo.toml +++ b/crates/rhema-claw/Cargo.toml @@ -76,6 +76,7 @@ time = { version = "0.3", default-features = false, features = ["parsing"] } # Inbound chat images ride base64; the dispatch decodes them into the # attachment store base64 = "0.22" +rhema-mcp = { version = "0.1.0", path = "../rhema-mcp" } [dev-dependencies] tempfile = "3" diff --git a/crates/rhema-claw/README.md b/crates/rhema-claw/README.md index ed87327..e91507e 100644 --- a/crates/rhema-claw/README.md +++ b/crates/rhema-claw/README.md @@ -18,6 +18,7 @@ model calls like any other). ```sh rhema-claw # serve on 127.0.0.1:7799 (config: listen) rhema-claw --once # one detect + one dispatch pass, then exit +claw mcp servers # the MCP meta surface (see rhema-mcp) ``` ### Coding jobs: the `coding_agent` tool diff --git a/crates/rhema-claw/src/main.rs b/crates/rhema-claw/src/main.rs index bc2cc60..c4c2184 100644 --- a/crates/rhema-claw/src/main.rs +++ b/crates/rhema-claw/src/main.rs @@ -32,11 +32,38 @@ struct Args { /// debug backend. Requires the `mock` feature. #[arg(long)] mock: bool, + + /// The MCP meta surface, the flat flags' first subcommand: + /// `claw mcp servers | tools | schema | call`. The rest goes to + /// the MCP CLI verbatim, which reads the bridge env the init + /// file set; outside a wired agent shell it exits 4 silently. + #[command(subcommand)] + command: Option, +} + +/// The claw's subcommands. +#[derive(Debug, clap::Subcommand)] +enum Command { + /// The MCP meta surface, passed through to `rhema_mcp::cli`. + Mcp { + /// The CLI's own argv, passed through untouched. + #[arg(allow_hyphen_values = true, trailing_var_arg = true)] + args: Vec, + }, } #[tokio::main] async fn main() { - if let Err(err) = run(Args::parse()).await { + // The MCP CLI owns the process when dispatched: its exit code is + // ours, its stdout/stderr contract is the caller's output. + let args = Args::parse(); + if let Some(Command::Mcp { args: rest }) = &args.command { + let mut argv = Vec::with_capacity(rest.len() + 1); + argv.push(std::ffi::OsString::from("mcp")); + argv.extend(rest.iter().cloned()); + std::process::exit(rhema_mcp::cli::run(&argv)); + } + if let Err(err) = run(args).await { eprintln!("error: {err}"); let mut source: &dyn std::error::Error = &err; while let Some(cause) = source.source() {