lean_ctx/tools/registered/
ctx_skillify.rs1use 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}