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