use serde_json::Value;
use super::{
types::{require_str, DispatchError},
McpServer,
};
fn required_index_id(server: &McpServer, args: &Value) -> Result<String, DispatchError> {
server.resolve_index_id(args).ok_or_else(|| {
DispatchError::InvalidParams("missing required string field: index_id".into())
})
}
pub(super) async fn dispatch_index_tool(
server: &McpServer,
tool: &str,
args: &Value,
) -> Option<Result<Value, DispatchError>> {
match tool {
"index_file" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let path = match require_str(args, "path") {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let content = match require_str(args, "content") {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
Some(
server
.post(
&format!("/indexes/{index_id}/index-file"),
&serde_json::json!({ "path": path, "content": content }),
)
.await,
)
}
"remove_file" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let path = match require_str(args, "path") {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
Some(
server
.post(
&format!("/indexes/{index_id}/remove-file"),
&serde_json::json!({ "path": path }),
)
.await,
)
}
"list_indexes" => Some(server.get("/indexes?details=true").await),
"create_index" => {
let id = match require_str(args, "id") {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let root_path = match require_str(args, "root_path") {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
Some(
server
.post(
"/indexes",
&serde_json::json!({ "id": id, "root_path": root_path }),
)
.await,
)
}
"delete_index" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
Some(server.delete(&format!("/indexes/{index_id}")).await)
}
"reindex" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let mut body = serde_json::json!({});
if let Some(rp) = args.get("root_path").and_then(Value::as_str) {
body["root_path"] = Value::String(rp.to_string());
}
Some(
server
.post(&format!("/indexes/{index_id}/reindex"), &body)
.await,
)
}
"index_status" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
Some(server.get(&format!("/indexes/{index_id}/status")).await)
}
"list_chunks" => {
let index_id = match required_index_id(server, args) {
Ok(v) => v,
Err(e) => return Some(Err(e)),
};
let offset = args.get("offset").and_then(Value::as_u64).unwrap_or(0);
let limit = args.get("limit").and_then(Value::as_u64).unwrap_or(100);
let mut query: Vec<(&str, String)> =
vec![("offset", offset.to_string()), ("limit", limit.to_string())];
if let Some(after) = args.get("after").and_then(Value::as_str) {
query.push(("after", after.to_string()));
}
Some(
server
.get_query(&format!("/indexes/{index_id}/chunks"), &query)
.await,
)
}
_ => None,
}
}