locus_mcp/tools/
list_nodes.rs1use locus_sdk::application::memory_find::MemoryFindService;
2use locus_sdk::domain::memory::{MemoryFilter, MemoryFindRequest, MemoryPage, MemoryScope};
3use serde_json::json;
4use tracing::error;
5
6use crate::{
7 ListNodesRequest, SttpMcpServer, expanded_limit, filter_nodes_by_context_keywords,
8 normalize_context_keywords, sttp_node_to_json, to_json_string, tool_error, validate_limit,
9};
10
11pub(crate) async fn execute(server: &SttpMcpServer, request: ListNodesRequest) -> String {
12 let limit = match validate_limit(request.limit, "limit") {
13 Ok(value) => value,
14 Err(message) => return tool_error("InvalidArgument", &message),
15 };
16 let context_keywords = normalize_context_keywords(request.context_keywords.as_deref());
17 let query_limit = if context_keywords.is_empty() {
18 limit
19 } else {
20 expanded_limit(limit)
21 };
22
23 let find_service = MemoryFindService::new(server.node_store.clone())
24 .with_semantic_index(server.semantic_index.clone());
25 let find_result = match find_service
26 .execute(&MemoryFindRequest {
27 scope: MemoryScope {
28 tenant_id: None,
29 session_ids: request.session_id.map(|session| vec![session]),
30 tiers: None,
31 from_utc: None,
32 to_utc: None,
33 },
34 filter: MemoryFilter {
35 indexed_tags: request.semantic_tags,
36 link_rel: request.link_rel,
37 link_target: request.link_target,
38 ..Default::default()
39 },
40 page: MemoryPage {
41 limit: query_limit,
42 cursor: None,
43 },
44 ..Default::default()
45 })
46 .await
47 {
48 Ok(result) => result,
49 Err(err) => {
50 error!(error = %err, "list_nodes failed");
51 return tool_error("ListNodesFailure", &err.to_string());
52 }
53 };
54
55 let nodes = if context_keywords.is_empty() {
56 find_result
57 .nodes
58 .into_iter()
59 .take(limit)
60 .collect::<Vec<_>>()
61 } else {
62 filter_nodes_by_context_keywords(&find_result.nodes, &context_keywords, limit)
63 };
64
65 to_json_string(json!({
66 "retrieved": nodes.len(),
67 "nodes": nodes
68 .iter()
69 .map(sttp_node_to_json)
70 .collect::<Vec<_>>()
71 }))
72}