pub mod initialize;
pub mod tools_call;
pub mod tools_list;
use axum::{Json, extract::State};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::mcp::server::ServerState;
#[derive(Debug, Deserialize)]
pub struct JsonRpcRequest {
#[allow(dead_code)]
pub jsonrpc: String,
pub id: Option<Value>,
pub method: String,
#[serde(default)]
pub params: Value,
}
#[derive(Debug, Serialize)]
pub struct JsonRpcResponse {
pub jsonrpc: String,
pub id: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<JsonRpcError>,
}
#[derive(Debug, Serialize)]
pub struct JsonRpcError {
pub code: i32,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
pub async fn handle_post(
State(state): State<ServerState>,
Json(req): Json<JsonRpcRequest>,
) -> Json<JsonRpcResponse> {
let id = req.id.clone();
let result = match req.method.as_str() {
"initialize" => initialize::handle(req.params).await,
"tools/list" => {
tools_list::handle(state.expose.as_ref(), state.schema.as_ref(), req.params).await
}
"tools/call" => tools_call::handle(&state, req.params).await,
"notifications/initialized" => Ok(Value::Null),
"ping" => Ok(serde_json::json!({})),
_ => Err(method_not_found(&req.method)),
};
Json(match result {
Ok(v) => JsonRpcResponse {
jsonrpc: "2.0".into(),
id,
result: Some(v),
error: None,
},
Err(e) => JsonRpcResponse {
jsonrpc: "2.0".into(),
id,
result: None,
error: Some(e),
},
})
}
fn method_not_found(method: &str) -> JsonRpcError {
JsonRpcError {
code: -32601,
message: format!("Method not found: {method}"),
data: None,
}
}