Skip to main content

lean_ctx/tools/registered/
ctx_skillify.rs

1use rmcp::model::Tool;
2use rmcp::ErrorData;
3use serde_json::{json, Map, Value};
4
5use crate::server::tool_trait::{get_str, McpTool, ToolContext, ToolOutput};
6use crate::tool_defs::tool_def;
7
8pub struct CtxSkillifyTool;
9
10impl McpTool for CtxSkillifyTool {
11    fn name(&self) -> &'static str {
12        "ctx_skillify"
13    }
14
15    fn tool_def(&self) -> Tool {
16        tool_def(
17            "ctx_skillify",
18            "Codify recurring patterns from this project's session diary + knowledge into versioned, git-committable .cursor/rules/skillify-*.mdc files. Actions: mine (distill & write/merge rules), list (show generated rules), status (config + counts), promote (copy a project rule to ~/.cursor/rules). Precision-biased; only acts when invoked; re-runs are idempotent.",
19            json!({
20                "type": "object",
21                "properties": {
22                    "action": {
23                        "type": "string",
24                        "enum": ["mine", "list", "status", "promote"],
25                        "description": "Skillify action (default: mine)"
26                    },
27                    "slug": {
28                        "type": "string",
29                        "description": "Rule slug for the promote action (e.g. skillify-stop-before-build)"
30                    }
31                }
32            }),
33        )
34    }
35
36    fn handle(
37        &self,
38        args: &Map<String, Value>,
39        ctx: &ToolContext,
40    ) -> Result<ToolOutput, ErrorData> {
41        let action = get_str(args, "action").unwrap_or_else(|| "mine".to_string());
42        let slug = get_str(args, "slug");
43        let result =
44            crate::tools::ctx_skillify::handle(&ctx.project_root, &action, slug.as_deref());
45        Ok(ToolOutput::simple(result))
46    }
47}