use serde::Deserialize;
use serde_json::Value;
use crate::mcp::error::McpError;
use crate::mcp::server::ServerState;
use crate::mcp::tools::{aggregate, get, list_sources, query, search};
use super::JsonRpcError;
#[derive(Deserialize)]
struct CallParams {
name: String,
#[serde(default)]
arguments: Value,
}
pub async fn handle(state: &ServerState, params: Value) -> Result<Value, JsonRpcError> {
let CallParams { name, arguments } = serde_json::from_value(params)
.map_err(|e| invalid_params(format!("invalid call params: {e}")))?;
let result: Value = match name.as_str() {
"search" => {
let req: search::SearchRequest = serde_json::from_value(arguments)
.map_err(|e| invalid_params(format!("search args: {e}")))?;
let resp = search::run(
state.search.as_ref(),
state.expose.as_ref(),
state.schema.as_ref(),
state.search_config.as_ref(),
req,
)
.await
.map_err(map_mcp_error)?;
serde_json::to_value(resp).unwrap()
}
"query" => {
let req: query::QueryRequest = serde_json::from_value(arguments)
.map_err(|e| invalid_params(format!("query args: {e}")))?;
let resp = query::run(state.cosmos.as_ref(), state.expose.as_ref(), req)
.await
.map_err(map_mcp_error)?;
serde_json::to_value(resp).unwrap()
}
"get" => {
let req: get::GetRequest = serde_json::from_value(arguments)
.map_err(|e| invalid_params(format!("get args: {e}")))?;
let resp = get::run(state.cosmos.as_ref(), state.expose.as_ref(), req)
.await
.map_err(map_mcp_error)?;
serde_json::to_value(resp).unwrap()
}
"aggregate" => {
let req: aggregate::AggregateRequest = serde_json::from_value(arguments)
.map_err(|e| invalid_params(format!("aggregate args: {e}")))?;
let resp = aggregate::run(
state.cosmos.as_ref(),
state.expose.as_ref(),
state.schema.as_ref(),
req,
)
.await
.map_err(map_mcp_error)?;
serde_json::to_value(resp).unwrap()
}
"list_sources" => {
let resp = list_sources::run(state.expose.as_ref(), state.schema.as_ref())
.await
.map_err(map_mcp_error)?;
serde_json::to_value(resp).unwrap()
}
other => return Err(invalid_params(format!("unknown tool: {other}"))),
};
let json_str = serde_json::to_string(&result).unwrap();
Ok(serde_json::json!({
"content": [{ "type": "text", "text": json_str }]
}))
}
fn invalid_params(msg: String) -> JsonRpcError {
JsonRpcError {
code: -32602,
message: msg,
data: None,
}
}
fn map_mcp_error(err: McpError) -> JsonRpcError {
let (code, msg) = match &err {
McpError::NotFound(_) => (-32004, format!("{err}")),
McpError::Forbidden(_) => (-32003, format!("{err}")),
McpError::InvalidArgument(_) => (-32602, format!("{err}")),
McpError::Unauthenticated(_) => (-32001, format!("{err}")),
McpError::Unavailable(_) => (-32005, format!("{err}")),
McpError::Internal(_) => (-32603, format!("{err}")),
McpError::Filter(_) => (-32602, format!("{err}")),
McpError::Cosmos(_) => (-32005, format!("{err}")),
};
JsonRpcError {
code,
message: msg,
data: None,
}
}