use elenchus_solver::verify_source;
use serde_json::{Value, json};
use crate::{messages, rpc};
pub fn definitions() -> Vec<Value> {
vec![check_def(), version_def(), about_def()]
}
fn check_def() -> Value {
json!({
"name": "elenchus_check",
"description": messages::CHECK_TOOL,
"inputSchema": {
"type": "object",
"properties": {
"program": { "type": "string", "description": messages::CHECK_ARG_PROGRAM },
"format": {
"type": "string",
"enum": ["human", "json"],
"description": messages::CHECK_ARG_FORMAT
}
},
"required": ["program"]
}
})
}
fn version_def() -> Value {
json!({
"name": "elenchus_version",
"description": messages::VERSION_TOOL,
"inputSchema": { "type": "object", "properties": {} }
})
}
fn about_def() -> Value {
json!({
"name": "elenchus_about",
"description": messages::ABOUT_TOOL,
"inputSchema": { "type": "object", "properties": {} }
})
}
pub fn call(id: Value, params: Option<&Value>) -> Value {
let Some(params) = params else {
return rpc::error(id, -32602, "missing params");
};
let name = params.get("name").and_then(Value::as_str).unwrap_or("");
match name {
"elenchus_version" => {
rpc::tool_result(id, format!("elenchus {}", env!("CARGO_PKG_VERSION")), false)
}
"elenchus_about" => rpc::tool_result(id, messages::ABOUT_TOOL.to_string(), false),
"elenchus_check" => check(id, params.get("arguments")),
other => rpc::tool_result(id, format!("unknown tool: {other}"), true),
}
}
fn check(id: Value, args: Option<&Value>) -> Value {
let Some(program) = args.and_then(|a| a.get("program")).and_then(Value::as_str) else {
return rpc::tool_result(id, "missing required argument: program".into(), true);
};
let format = args
.and_then(|a| a.get("format"))
.and_then(Value::as_str)
.unwrap_or("json");
match verify_source("<mcp>", program) {
Ok(report) => {
let text = if format == "human" {
format!("{report}")
} else {
report.to_json()
};
rpc::tool_result(id, text, false)
}
Err(e) => rpc::tool_result(id, e.to_string(), true),
}
}