lean_ctx_server/tools/registered/
ctx_tools.rs1use rmcp::ErrorData;
3use rmcp::model::Tool;
4use serde_json::{Map, Value, json};
5
6use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput};
7use lean_ctx::tool_defs::tool_def;
8
9pub struct CtxToolsTool;
13
14impl McpTool for CtxToolsTool {
15 fn name(&self) -> &'static str {
16 "ctx_tools"
17 }
18
19 fn tool_def(&self) -> Tool {
20 tool_def(
21 "ctx_tools",
22 "Gateway to downstream MCP servers — unlimited external tools at ~constant context cost.\n\
23 actions: find (query → top-N relevant tools) | call (proxy a server::tool) |\n\
24 list (servers+counts) | refresh.\n\
25 WORKFLOW: find to discover, then call the chosen server::tool.\n\
26 ANTIPATTERN: not for built-in tools — use those directly.",
27 json!({
28 "type": "object",
29 "properties": {
30 "action": {
31 "type": "string",
32 "enum": ["find", "call", "list", "refresh"],
33 "description": "find|call|list|refresh"
34 },
35 "query": { "type": "string", "description": "What you want to do (for find)" },
36 "tool": { "type": "string", "description": "`server::tool` handle (for call)" },
37 "arguments": { "type": "object", "description": "Arguments for downstream tool (call)" }
38 },
39 "allOf": [
40 {
41 "if": { "properties": { "action": { "const": "call" } }, "required": ["action"] },
42 "then": { "required": ["action", "tool"] }
43 }
44 ]
45 }),
46 )
47 }
48
49 fn handle(
50 &self,
51 args: &Map<String, Value>,
52 ctx: &ToolContext,
53 ) -> Result<ToolOutput, ErrorData> {
54 match crate::tools::ctx_tools::run(args, &ctx.project_root) {
58 Ok(text) => Ok(ToolOutput::simple(text)),
59 Err(e) => Err(ErrorData::invalid_params(e, None)),
60 }
61 }
62}