1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3#![cfg_attr(
4 not(test),
5 deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)
6)]
7
8pub mod tools;
14pub mod types;
15
16use rmcp::handler::server::router::tool::ToolRouter;
17use rmcp::handler::server::tool::ToolCallContext;
18use rmcp::handler::server::wrapper::Parameters;
19use rmcp::model::{
20 CallToolRequestParams, CallToolResult, Implementation, ListToolsResult, PaginatedRequestParams,
21 ServerCapabilities, ServerInfo,
22};
23use rmcp::service::{RequestContext, RoleServer};
24use rmcp::{ErrorData as McpError, ServerHandler, tool, tool_router};
25
26use crate::types::*;
27
28#[derive(Clone)]
29pub struct SkillsMcpServer {
30 tool_router: ToolRouter<Self>,
31}
32
33#[tool_router]
34impl SkillsMcpServer {
35 pub fn new() -> Result<Self, nexcore_error::NexError> {
36 Ok(Self {
37 tool_router: Self::tool_router(),
38 })
39 }
40
41 #[tool(
46 description = "VITALS [V] Vigor: Check hormone state (cortisol, dopamine, serotonin, adrenaline, oxytocin, melatonin). Returns levels, staleness, and health assessment."
47 )]
48 async fn vitals_vigor(
49 &self,
50 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
51 ) -> Result<CallToolResult, McpError> {
52 tools::vitals::vigor()
53 }
54
55 #[tool(
56 description = "VITALS [I] Immunity: Query antibody registry from brain.db. Returns PAMP/DAMP counts, severity distribution, and coverage assessment."
57 )]
58 async fn vitals_immunity(
59 &self,
60 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
61 ) -> Result<CallToolResult, McpError> {
62 tools::vitals::immunity()
63 }
64
65 #[tool(
66 description = "VITALS [T] Telemetry: Check signal processing health. Returns signal count, type distribution, and receiver status."
67 )]
68 async fn vitals_telemetry(
69 &self,
70 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
71 ) -> Result<CallToolResult, McpError> {
72 tools::vitals::telemetry()
73 }
74
75 #[tool(
76 description = "VITALS [A] Antibodies: Deep-dive into antibody detection and response patterns. Returns detailed roster with threat types and confidence."
77 )]
78 async fn vitals_antibodies(
79 &self,
80 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
81 ) -> Result<CallToolResult, McpError> {
82 tools::vitals::antibodies()
83 }
84
85 #[tool(
86 description = "VITALS [L] Lifespan: Brain session persistence check. Returns session count, DB table sizes, code tracker, and implicit knowledge stats."
87 )]
88 async fn vitals_lifespan(
89 &self,
90 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
91 ) -> Result<CallToolResult, McpError> {
92 tools::vitals::lifespan()
93 }
94
95 #[tool(
96 description = "VITALS [S] Synapse: Connection health and biological score (0-100). Computes overall health grade from all subsystems."
97 )]
98 async fn vitals_synapse(
99 &self,
100 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
101 ) -> Result<CallToolResult, McpError> {
102 tools::vitals::synapse()
103 }
104
105 #[tool(
106 description = "VITALS full pipeline: Run all 6 phases (Vigor→Immunity→Telemetry→Antibodies→Lifespan→Synapse) and return combined health report with score and grade."
107 )]
108 async fn vitals_pipeline(
109 &self,
110 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
111 ) -> Result<CallToolResult, McpError> {
112 tools::vitals::pipeline()
113 }
114
115 #[tool(
120 description = "LEARN [L] Landscape: Survey all data sources (signals, sessions, brain.db tables, implicit knowledge, hormones). Returns counts and freshness."
121 )]
122 async fn learn_landscape(
123 &self,
124 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
125 ) -> Result<CallToolResult, McpError> {
126 tools::learn::landscape()
127 }
128
129 #[tool(
130 description = "LEARN [E] Extract: Mine patterns from signals (blocked tools, failures), vocabulary counters (hit rate, dead weight), and brain DB. Returns extracted patterns."
131 )]
132 async fn learn_extract(
133 &self,
134 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
135 ) -> Result<CallToolResult, McpError> {
136 tools::learn::extract()
137 }
138
139 #[tool(
140 description = "LEARN [A] Assimilate: Write extracted patterns to implicit/patterns.json and brain.db patterns table. Deduplicates by type+source."
141 )]
142 async fn learn_assimilate(
143 &self,
144 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
145 ) -> Result<CallToolResult, McpError> {
146 tools::learn::assimilate()
147 }
148
149 #[tool(
150 description = "LEARN [R] Recall: Verify knowledge loads correctly. Tests MEMORY.md, preferences, patterns, sessions, antibodies, and hook-knowledge bridge. Returns recall score (N/6)."
151 )]
152 async fn learn_recall(
153 &self,
154 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
155 ) -> Result<CallToolResult, McpError> {
156 tools::learn::recall()
157 }
158
159 #[tool(
160 description = "LEARN [N] Normalize: Prune dead weight vocabulary, deduplicate patterns, rotate large signal files. Returns items pruned."
161 )]
162 async fn learn_normalize(
163 &self,
164 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
165 ) -> Result<CallToolResult, McpError> {
166 tools::learn::normalize()
167 }
168
169 #[tool(
170 description = "LEARN full pipeline: Run all 5 phases (Landscape→Extract→Assimilate→Recall→Normalize) and return combined learning report."
171 )]
172 async fn learn_pipeline(
173 &self,
174 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
175 ) -> Result<CallToolResult, McpError> {
176 tools::learn::pipeline()
177 }
178
179 #[tool(
184 description = "PROVE [P] Prepare: Check Claude CLI, MCP binary, brain DB, settings.json. Capture baseline snapshot."
185 )]
186 async fn prove_prepare(
187 &self,
188 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
189 ) -> Result<CallToolResult, McpError> {
190 tools::prove::prepare()
191 }
192
193 #[tool(
194 description = "PROVE [O] Observe: Parse the most recent sub-Claude run output into structured findings (brain, immunity, hormones status)."
195 )]
196 async fn prove_observe(
197 &self,
198 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
199 ) -> Result<CallToolResult, McpError> {
200 tools::prove::observe()
201 }
202
203 #[tool(
204 description = "PROVE [V] Validate: Compare observed findings against baselines. Returns pass/fail for each check."
205 )]
206 async fn prove_validate(
207 &self,
208 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
209 ) -> Result<CallToolResult, McpError> {
210 tools::prove::validate()
211 }
212
213 #[tool(
214 description = "PROVE [E] Evaluate: Score and track improvement over time. Appends to history, computes trend (IMPROVING/STABLE/REGRESSING)."
215 )]
216 async fn prove_evaluate(
217 &self,
218 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
219 ) -> Result<CallToolResult, McpError> {
220 tools::prove::evaluate()
221 }
222
223 #[tool(
228 description = "Run any vocabulary program or individual phase. Programs: SMART, BRAIN, GUARD, PULSE, FORGE, SCOPE, CLEAN, AUDIT, CRAFT, TRACE. Use program='clean' and phase='ALL' for full pipeline, or phase='C' for a single letter."
229 )]
230 async fn skill_run(
231 &self,
232 Parameters(params): Parameters<SkillRunParams>,
233 ) -> Result<CallToolResult, McpError> {
234 tools::runner::run_skill(params).await
235 }
236
237 #[tool(
238 description = "List all available vocabulary programs with their phases and descriptions."
239 )]
240 async fn skill_list(
241 &self,
242 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
243 ) -> Result<CallToolResult, McpError> {
244 tools::runner::list_skills()
245 }
246
247 #[tool(
252 description = "Decompose a concept, problem, or code pattern into its T1 Lex Primitiva components. Returns identified primitives with relevance scores, dominant primitive, tier classification, and composition formula. Examples: 'rate limiter', 'cache invalidation', 'login authentication', 'HashMap<K,V>'."
253 )]
254 async fn primitive_decompose(
255 &self,
256 Parameters(params): Parameters<PrimitiveDecomposeParams>,
257 ) -> Result<CallToolResult, McpError> {
258 tools::primitives::decompose(params)
259 }
260
261 #[tool(
262 description = "Given T1 primitive names or symbols, describe what they compose into. Returns known patterns, tier classification, and Rust implementation suggestions. Examples: ['Sequence', 'Mapping', 'Boundary'] or ['σ', 'μ', '∂']."
263 )]
264 async fn primitive_compose(
265 &self,
266 Parameters(params): Parameters<PrimitiveComposeParams>,
267 ) -> Result<CallToolResult, McpError> {
268 tools::primitives::compose(params)
269 }
270
271 #[tool(
272 description = "List all 16 T1 Lex Primitiva symbols with their meanings and Rust manifestations. The irreducible universal primitives that ground all higher-tier types."
273 )]
274 async fn primitive_list(
275 &self,
276 #[allow(unused)] Parameters(params): Parameters<EmptyParams>,
277 ) -> Result<CallToolResult, McpError> {
278 tools::primitives::list_all()
279 }
280}
281
282impl ServerHandler for SkillsMcpServer {
283 fn get_info(&self) -> ServerInfo {
284 ServerInfo {
285 instructions: Some("Skills MCP: vocabulary programs as tools. LEARN (feedback loop), PROVE (self-verification), VITALS (biological health), plus generic runner for SMART/BRAIN/GUARD/PULSE/FORGE/SCOPE/CLEAN/AUDIT/CRAFT/TRACE.".into()),
286 capabilities: ServerCapabilities::builder().enable_tools().build(),
287 server_info: Implementation {
288 name: "skills-mcp".into(),
289 version: env!("CARGO_PKG_VERSION").into(),
290 title: Some("Skills MCP Server".into()),
291 icons: None,
292 website_url: None,
293 },
294 ..Default::default()
295 }
296 }
297
298 fn call_tool(
299 &self,
300 request: CallToolRequestParams,
301 context: RequestContext<RoleServer>,
302 ) -> impl std::future::Future<Output = Result<CallToolResult, McpError>> + Send + '_ {
303 async move {
304 let tcc = ToolCallContext::new(self, request, context);
305 let result = self.tool_router.call(tcc).await?;
306 Ok(result)
307 }
308 }
309
310 fn list_tools(
311 &self,
312 _request: Option<PaginatedRequestParams>,
313 _context: RequestContext<RoleServer>,
314 ) -> impl std::future::Future<Output = Result<ListToolsResult, McpError>> + Send + '_ {
315 std::future::ready(Ok(ListToolsResult {
316 tools: self.tool_router.list_all(),
317 meta: None,
318 next_cursor: None,
319 }))
320 }
321}