Skip to main content

lean_ctx_server/tools/registered/
ctx_share.rs

1// SPDX-License-Identifier: Apache-2.0
2use 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}