1use serde_json::Value;
8
9use crate::protocol::ToolCallResult;
10use crate::server::ServerContext;
11
12pub fn paper_resolve_pdf(args: &Value, ctx: &ServerContext) -> ToolCallResult {
16 let doi = args.get("doi").and_then(|v| v.as_str());
17 let title = args.get("title").and_then(|v| v.as_str());
18 let url = args.get("url").and_then(|v| v.as_str());
19
20 if doi.is_none() && title.is_none() && url.is_none() {
21 return ToolCallResult::error("Provide at least one of: doi, title, url".into());
22 }
23
24 let report = paper_resolver::resolve_pdf_with_report(doi, url, title, &ctx.config.resolver);
25
26 ToolCallResult::text(report.summary())
27}
28
29pub fn paper_source_status(ctx: &ServerContext) -> ToolCallResult {
33 let config = &ctx.config.resolver;
34 let mut output = String::from("Paper Resolver Configuration\n\n");
35
36 output.push_str(&format!("Email: {}\n", config.email));
37 output.push_str(&format!("User-Agent: {}\n", config.user_agent));
38 output.push_str(&format!("Timeout: {}s\n", config.timeout_secs));
39 output.push_str(&format!(
40 "Extra blocked domains: {}\n\n",
41 if config.extra_blocked_domains.is_empty() {
42 "(none)".into()
43 } else {
44 config.extra_blocked_domains.join(", ")
45 }
46 ));
47
48 output.push_str("Sources (priority order):\n");
49 for (i, source) in config.sources.iter().enumerate() {
50 let status = if source.enabled {
51 "enabled"
52 } else {
53 "disabled"
54 };
55 output.push_str(&format!(" {}. {} [{}]\n", i + 1, source.name, status));
56 }
57
58 ToolCallResult::text(output)
59}