use clap::Parser;
use std::io::{self, BufRead, Write};
use std::fs::OpenOptions;
mod json_tools;
mod mcp;
use json_tools::JsonToolsHandler;
use mcp::{
protocol::MCPResponse,
server::MCPServer,
};
#[derive(Parser)]
#[command(
name = "json-mcp-server",
about = "A Model Context Protocol server for JSON file operations"
)]
struct Args {
#[arg(short, long, default_value = "off")]
log_level: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let _args = Args::parse();
let mut debug_log = OpenOptions::new()
.create(true)
.append(true)
.open("mcp_debug.log")
.ok();
let json_handler = JsonToolsHandler::new();
let mut server = MCPServer::new(json_handler);
server.register_tools().await?;
let stdin = io::stdin();
let mut stdout = io::stdout();
for line in stdin.lock().lines() {
match line {
Ok(input) => {
if input.trim().is_empty() {
continue;
}
if let Some(ref mut log) = debug_log {
let timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%.3f");
let _ = writeln!(log, "[{}] INCOMING: {}", timestamp, input);
let _ = log.flush();
}
match server.handle_request(&input).await {
Ok(response) => {
if let Some(ref mut log) = debug_log {
let timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%.3f");
let _ = writeln!(log, "[{}] OUTGOING: {}", timestamp, response);
let _ = log.flush();
}
if let Err(_e) = writeln!(stdout, "{}", response) {
break;
}
if let Err(_e) = stdout.flush() {
break;
}
}
Err(e) => {
let error_response = MCPResponse::error(
None,
-32603,
&format!("Internal error: {}", e),
);
let response_str = serde_json::to_string(&error_response)?;
if let Some(ref mut log) = debug_log {
let timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%.3f");
let _ = writeln!(log, "[{}] ERROR_OUTGOING: {}", timestamp, response_str);
let _ = log.flush();
}
if let Err(_e) = writeln!(stdout, "{}", response_str) {
break;
}
if let Err(_e) = stdout.flush() {
break;
}
}
}
}
Err(_e) => {
break;
}
}
}
Ok(())
}