use crate::error::not_implemented_result;
use rmcp::{handler::server::wrapper::Parameters, model::CallToolResult, ErrorData as McpError};
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ExecParams {
pub cmd: Vec<String>,
}
pub(crate) async fn handle(
_state: &crate::ServerState,
Parameters(_p): Parameters<ExecParams>,
) -> Result<CallToolResult, McpError> {
Ok(not_implemented_result("exec"))
}
#[cfg(test)]
mod tests {
use super::*;
use rmcp::handler::server::tool::schema_for_type;
use serde_json::Value;
#[test]
fn exec_params_schema_resolves() {
let _ = schema_for_type::<ExecParams>();
}
#[test]
fn exec_tool_schema_has_no_shell_field() {
let schema = schema_for_type::<ExecParams>();
let v: Value = serde_json::to_value(&*schema).expect("schema → json");
let props = v.get("properties").and_then(|p| p.as_object());
if let Some(p) = props {
assert!(
!p.contains_key("shell"),
"exec MCP schema must not advertise `shell`; got {p:?}"
);
}
assert!(
props.map(|p| p.contains_key("cmd")).unwrap_or(false),
"exec schema missing required `cmd` field; schema = {v}"
);
}
#[tokio::test]
async fn exec_happy_path_stub() {
let s = crate::ServerState::for_tests();
let r = handle(&s, Parameters(ExecParams { cmd: vec!["echo".into()] })).await.unwrap();
assert_eq!(r.is_error, Some(true));
}
}