rab/extensions/mcp/
cache.rs1use crate::extensions::mcp::types::{CachedTool, MetadataCache, ServerCacheEntry};
5use std::collections::HashMap;
6use std::path::PathBuf;
7
8const CACHE_VERSION: u32 = 1;
9
10fn cache_path() -> PathBuf {
12 directories::BaseDirs::new()
13 .map(|d| {
14 d.home_dir()
15 .join(".rab")
16 .join("agent")
17 .join("mcp-cache.json")
18 })
19 .unwrap_or_else(|| PathBuf::from("/tmp/.rab/agent/mcp-cache.json"))
20}
21
22pub fn load_cache() -> MetadataCache {
24 let path = cache_path();
25 if !path.exists() {
26 return MetadataCache {
27 version: CACHE_VERSION,
28 servers: HashMap::new(),
29 };
30 }
31 let content = match std::fs::read_to_string(&path) {
32 Ok(c) => c,
33 Err(_) => {
34 return MetadataCache {
35 version: CACHE_VERSION,
36 servers: HashMap::new(),
37 };
38 }
39 };
40 let cache: MetadataCache = match serde_json::from_str(&content) {
41 Ok(c) => c,
42 Err(_) => MetadataCache {
43 version: CACHE_VERSION,
44 servers: HashMap::new(),
45 },
46 };
47 if cache.version != CACHE_VERSION {
49 return MetadataCache {
50 version: CACHE_VERSION,
51 servers: HashMap::new(),
52 };
53 }
54 cache
55}
56
57pub fn save_cache(cache: &MetadataCache) {
59 let path = cache_path();
60 if let Some(parent) = path.parent() {
61 let _ = std::fs::create_dir_all(parent);
62 }
63 if let Ok(content) = serde_json::to_string(cache) {
64 let _ = std::fs::write(&path, &content);
65 }
66}
67
68pub fn update_cache_entry(
70 server_name: &str,
71 config_hash: u64,
72 yo_tools: &[yoagent::mcp::types::McpToolInfo],
73) {
74 let mut cache = load_cache();
75 let tools: Vec<CachedTool> = yo_tools
76 .iter()
77 .map(|t| CachedTool {
78 name: t.name.clone(),
79 description: t.description.clone(),
80 input_schema: if t.input_schema.is_null() {
81 serde_json::json!({"type": "object", "properties": {}})
82 } else {
83 t.input_schema.clone()
84 },
85 })
86 .collect();
87
88 cache.servers.insert(
89 server_name.to_string(),
90 ServerCacheEntry {
91 config_hash,
92 tools,
93 cached_at: std::time::SystemTime::now()
94 .duration_since(std::time::UNIX_EPOCH)
95 .map(|d| d.as_millis() as u64)
96 .unwrap_or(0),
97 },
98 );
99 save_cache(&cache);
100}
101
102pub fn has_valid_cache(server_name: &str, config_hash: u64) -> bool {
104 let cache = load_cache();
105 cache
106 .servers
107 .get(server_name)
108 .is_some_and(|e| e.config_hash == config_hash)
109}