use clap::{Args, Subcommand};
use super::registry;
#[derive(Args, Debug)]
pub struct VerbArgs {
#[command(subcommand)]
pub cmd: VerbCmd,
}
#[derive(Subcommand, Debug)]
pub enum VerbCmd {
List {
#[arg(long)]
json: bool,
},
Schema {
name: String,
},
Serve {
#[arg(long, default_value = "8737")]
port: u16,
#[arg(long, default_value = "127.0.0.1")]
bind: String,
},
Call {
name: String,
#[arg(long, default_value = "{}")]
json: String,
},
}
pub fn dispatch_verb(cmd: VerbCmd) -> Result<(), String> {
match cmd {
VerbCmd::List { json } => list(json),
VerbCmd::Schema { name } => schema(&name),
VerbCmd::Call { name, json } => call(&name, &json),
VerbCmd::Serve { port, bind } => super::http::serve(super::http::HttpConfig { bind, port }),
}
}
fn list(as_json: bool) -> Result<(), String> {
let verbs = registry::verbs();
if as_json {
let rows: Vec<_> = verbs
.iter()
.map(|v| {
serde_json::json!({
"name": v.name,
"mcp_name": v.mcp_name(),
"description": v.description,
"read_only": v.effects.read_only(),
"timeout_ms": v.timeout_ms,
})
})
.collect();
let out = serde_json::to_string_pretty(&serde_json::json!({ "verbs": rows }))
.map_err(|e| format!("JSON error: {e}"))?;
println!("{out}");
} else {
for v in &verbs {
println!("{}", v.name);
}
}
Ok(())
}
fn schema(name: &str) -> Result<(), String> {
let v = registry::find(name).ok_or_else(|| unknown(name))?;
let out = serde_json::to_string_pretty(&serde_json::json!({
"name": v.name,
"input_schema": (v.input_schema)(),
"output_schema": (v.output_schema)(),
}))
.map_err(|e| format!("JSON error: {e}"))?;
println!("{out}");
Ok(())
}
fn call(name: &str, params: &str) -> Result<(), String> {
let v = registry::find(name).ok_or_else(|| unknown(name))?;
let value: serde_json::Value =
serde_json::from_str(params).map_err(|e| format!("--json is not valid JSON: {e}"))?;
let out = (v.invoke)(value)?;
println!("{}", super::render_result(&out));
Ok(())
}
fn unknown(name: &str) -> String {
let names: Vec<&str> = registry::verbs().iter().map(|v| v.name).collect();
format!(
"unknown verb `{name}` — the unified surface is: {}",
names.join(", ")
)
}