lean_ctx_server/tools/registered/
ctx_share.rs1use rmcp::ErrorData;
3use rmcp::model::Tool;
4use serde_json::{Map, Value, json};
5
6use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str};
7use lean_ctx::tool_defs::tool_def;
8
9pub struct CtxShareTool;
10
11impl McpTool for CtxShareTool {
12 fn name(&self) -> &'static str {
13 "ctx_share"
14 }
15
16 fn tool_def(&self) -> Tool {
17 tool_def(
18 "ctx_share",
19 "WORKFLOW: push from agent A → pull from agent B shares cached file contexts.\n\
20 Actions: push|pull|list|clear. Omit to_agent for broadcast.\n\
21 ANTIPATTERN: NOT file transfer — shares lean-ctx cache entries only.",
22 json!({
23 "type": "object",
24 "properties": {
25 "action": {
26 "type": "string",
27 "enum": ["push", "pull", "list", "clear"],
28 "description": "push|pull|list|clear"
29 },
30 "paths": {
31 "type": "string",
32 "description": "Comma-separated paths (for push)"
33 },
34 "to_agent": {
35 "type": "string",
36 "description": "Target agent ID (omit for broadcast)"
37 },
38 "message": {
39 "type": "string",
40 "description": "Context message about what was shared"
41 }
42 },
43 "allOf": [
44 {
45 "if": {
46 "properties": { "action": { "const": "push" } },
47 "required": ["action"]
48 },
49 "then": {
50 "required": ["action", "paths"]
51 }
52 }
53 ],
54 "required": ["action"]
55 }),
56 )
57 }
58
59 fn handle(
60 &self,
61 args: &Map<String, Value>,
62 ctx: &ToolContext,
63 ) -> Result<ToolOutput, ErrorData> {
64 let action = get_str(args, "action")
65 .ok_or_else(|| ErrorData::invalid_params("action is required", None))?;
66 let to_agent = get_str(args, "to_agent");
67 let paths = get_str(args, "paths");
68 let message = get_str(args, "message");
69
70 let from_agent = ctx
71 .agent_id
72 .as_ref()
73 .map(|a| a.blocking_read().clone())
74 .unwrap_or_default();
75
76 let cache_handle = ctx
77 .cache
78 .as_ref()
79 .ok_or_else(|| ErrorData::internal_error("cache not available", None))?;
80 let cache = cache_handle.blocking_read();
81 let result = crate::tools::ctx_share::handle(
82 &action,
83 from_agent.as_deref(),
84 to_agent.as_deref(),
85 paths.as_deref(),
86 message.as_deref(),
87 &cache,
88 &ctx.project_root,
89 );
90 drop(cache);
91
92 Ok(ToolOutput {
93 text: result,
94 original_tokens: 0,
95 saved_tokens: 0,
96 mode: Some(action),
97 path: None,
98 changed: false,
99 shell_outcome: None,
100 content_blocks: None,
101 })
102 }
103}