use std::io::{self, BufRead, Write};
use serde_json::{Value, json};
use crate::{messages, tools};
pub fn run() {
let stdin = io::stdin();
let stdout = io::stdout();
let mut out = stdout.lock();
for line in stdin.lock().lines() {
let Ok(line) = line else { break };
if line.trim().is_empty() {
continue;
}
let Ok(req) = serde_json::from_str::<Value>(&line) else {
continue; };
if let Some(response) = handle(&req) {
let _ = writeln!(out, "{response}");
let _ = out.flush();
}
}
}
fn handle(req: &Value) -> Option<Value> {
let method = req.get("method")?.as_str()?;
let id = req.get("id").cloned();
match method {
"initialize" => id.map(|id| {
result(
id,
json!({
"protocolVersion": messages::PROTOCOL_VERSION,
"capabilities": { "tools": {} },
"serverInfo": { "name": messages::SERVER_NAME, "version": env!("CARGO_PKG_VERSION") }
}),
)
}),
"notifications/initialized" => None,
"ping" => id.map(|id| result(id, json!({}))),
"tools/list" => id.map(|id| result(id, json!({ "tools": tools::definitions() }))),
"tools/call" => id.map(|id| tools::call(id, req.get("params"))),
_ => id.map(|id| error(id, -32601, "method not found")),
}
}
pub fn result(id: Value, result: Value) -> Value {
json!({ "jsonrpc": "2.0", "id": id, "result": result })
}
pub fn error(id: Value, code: i64, message: &str) -> Value {
json!({ "jsonrpc": "2.0", "id": id, "error": { "code": code, "message": message } })
}
pub fn tool_result(id: Value, text: String, is_error: bool) -> Value {
result(
id,
json!({ "content": [{ "type": "text", "text": text }], "isError": is_error }),
)
}