Skip to main content

lean_ctx/tools/registered/
ctx_share.rs

1use 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}