@kinqs/brainrouter-mcp-server 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/.env.example +144 -0
  2. package/README.md +56 -0
  3. package/agents/README.md +120 -0
  4. package/agents/code-reviewer.md +97 -0
  5. package/agents/security-auditor.md +101 -0
  6. package/agents/test-engineer.md +95 -0
  7. package/dist/__tests__/agent_mode.test.d.ts +1 -0
  8. package/dist/__tests__/api-routes.test.d.ts +1 -0
  9. package/dist/__tests__/api-routes.test.js +170 -0
  10. package/dist/__tests__/crypto.test.d.ts +1 -0
  11. package/dist/__tests__/crypto.test.js +28 -0
  12. package/dist/__tests__/host-integrations.test.d.ts +1 -0
  13. package/dist/__tests__/host-integrations.test.js +82 -0
  14. package/dist/__tests__/integration.test.d.ts +1 -0
  15. package/dist/__tests__/integration.test.js +50 -0
  16. package/dist/__tests__/loader.test.d.ts +1 -0
  17. package/dist/__tests__/loader.test.js +89 -0
  18. package/dist/__tests__/neural-spark.test.d.ts +1 -0
  19. package/dist/__tests__/neural-spark.test.js +112 -0
  20. package/dist/__tests__/pagination.test.d.ts +1 -0
  21. package/dist/__tests__/pagination.test.js +23 -0
  22. package/dist/__tests__/redaction.test.d.ts +1 -0
  23. package/dist/__tests__/redaction.test.js +17 -0
  24. package/dist/__tests__/registry.test.d.ts +1 -0
  25. package/dist/__tests__/registry.test.js +56 -0
  26. package/dist/__tests__/retry.test.d.ts +1 -0
  27. package/dist/__tests__/retry.test.js +30 -0
  28. package/dist/__tests__/skill-activation.test.d.ts +1 -0
  29. package/dist/__tests__/skill-activation.test.js +112 -0
  30. package/dist/__tests__/working-memory.test.d.ts +1 -0
  31. package/dist/__tests__/working-memory.test.js +200 -0
  32. package/dist/__tests__/workspace-paths.test.d.ts +1 -0
  33. package/dist/__tests__/workspace-paths.test.js +56 -0
  34. package/dist/__tests__/writer.test.d.ts +1 -0
  35. package/dist/__tests__/writer.test.js +94 -0
  36. package/dist/api/auth/crypto.d.ts +4 -0
  37. package/dist/api/auth/crypto.js +54 -0
  38. package/dist/api/middleware/auth.d.ts +12 -0
  39. package/dist/api/middleware/auth.js +90 -0
  40. package/dist/api/pagination.d.ts +18 -0
  41. package/dist/api/pagination.js +32 -0
  42. package/dist/api/routes/auth.d.ts +1 -0
  43. package/dist/api/routes/auth.js +130 -0
  44. package/dist/api/routes/chat-completions.d.ts +7 -0
  45. package/dist/api/routes/chat-completions.js +474 -0
  46. package/dist/api/routes/contradictions.d.ts +1 -0
  47. package/dist/api/routes/contradictions.js +28 -0
  48. package/dist/api/routes/evidence.d.ts +1 -0
  49. package/dist/api/routes/evidence.js +59 -0
  50. package/dist/api/routes/governance.d.ts +1 -0
  51. package/dist/api/routes/governance.js +95 -0
  52. package/dist/api/routes/graph.d.ts +1 -0
  53. package/dist/api/routes/graph.js +25 -0
  54. package/dist/api/routes/hooks.d.ts +1 -0
  55. package/dist/api/routes/hooks.js +88 -0
  56. package/dist/api/routes/memories.d.ts +1 -0
  57. package/dist/api/routes/memories.js +92 -0
  58. package/dist/api/routes/persona.d.ts +1 -0
  59. package/dist/api/routes/persona.js +9 -0
  60. package/dist/api/routes/scenes.d.ts +1 -0
  61. package/dist/api/routes/scenes.js +35 -0
  62. package/dist/api/routes/skills.d.ts +1 -0
  63. package/dist/api/routes/skills.js +14 -0
  64. package/dist/api/routes/stats.d.ts +1 -0
  65. package/dist/api/routes/stats.js +8 -0
  66. package/dist/api/routes/users.d.ts +1 -0
  67. package/dist/api/routes/users.js +82 -0
  68. package/dist/api/routes/working.d.ts +1 -0
  69. package/dist/api/routes/working.js +88 -0
  70. package/dist/index.d.ts +2 -0
  71. package/dist/index.js +492 -0
  72. package/dist/integrations/claude-code.d.ts +12 -0
  73. package/dist/integrations/claude-code.js +35 -0
  74. package/dist/integrations/codex.d.ts +12 -0
  75. package/dist/integrations/codex.js +34 -0
  76. package/dist/integrations/generic-mcp.d.ts +52 -0
  77. package/dist/integrations/generic-mcp.js +118 -0
  78. package/dist/loader.d.ts +29 -0
  79. package/dist/loader.js +200 -0
  80. package/dist/memory/capture.d.ts +35 -0
  81. package/dist/memory/capture.js +230 -0
  82. package/dist/memory/config.d.ts +2 -0
  83. package/dist/memory/config.js +3 -0
  84. package/dist/memory/engine.d.ts +203 -0
  85. package/dist/memory/engine.js +626 -0
  86. package/dist/memory/llm-semaphore.d.ts +41 -0
  87. package/dist/memory/llm-semaphore.js +81 -0
  88. package/dist/memory/memory-type-config.d.ts +11 -0
  89. package/dist/memory/memory-type-config.js +65 -0
  90. package/dist/memory/pipeline/cognitive-contradiction.d.ts +7 -0
  91. package/dist/memory/pipeline/cognitive-contradiction.js +59 -0
  92. package/dist/memory/pipeline/cognitive-dedup.d.ts +23 -0
  93. package/dist/memory/pipeline/cognitive-dedup.js +38 -0
  94. package/dist/memory/pipeline/cognitive-extractor.d.ts +21 -0
  95. package/dist/memory/pipeline/cognitive-extractor.js +183 -0
  96. package/dist/memory/pipeline/contextual-focus-builder.d.ts +13 -0
  97. package/dist/memory/pipeline/contextual-focus-builder.js +135 -0
  98. package/dist/memory/pipeline/focus-direction-shift.d.ts +10 -0
  99. package/dist/memory/pipeline/focus-direction-shift.js +27 -0
  100. package/dist/memory/pipeline/graph-builder.d.ts +11 -0
  101. package/dist/memory/pipeline/graph-builder.js +88 -0
  102. package/dist/memory/pipeline/graph-recall.d.ts +13 -0
  103. package/dist/memory/pipeline/graph-recall.js +55 -0
  104. package/dist/memory/pipeline/identity-distiller.d.ts +15 -0
  105. package/dist/memory/pipeline/identity-distiller.js +40 -0
  106. package/dist/memory/pipeline/l1-contradiction.d.ts +7 -0
  107. package/dist/memory/pipeline/l1-contradiction.js +66 -0
  108. package/dist/memory/pipeline/l1-dedup.d.ts +23 -0
  109. package/dist/memory/pipeline/l1-dedup.js +39 -0
  110. package/dist/memory/pipeline/l1-extractor.d.ts +21 -0
  111. package/dist/memory/pipeline/l1-extractor.js +180 -0
  112. package/dist/memory/pipeline/l2-direction-shift.d.ts +10 -0
  113. package/dist/memory/pipeline/l2-direction-shift.js +27 -0
  114. package/dist/memory/pipeline/l2-scene.d.ts +15 -0
  115. package/dist/memory/pipeline/l2-scene.js +140 -0
  116. package/dist/memory/pipeline/l3-distiller.d.ts +15 -0
  117. package/dist/memory/pipeline/l3-distiller.js +40 -0
  118. package/dist/memory/pipeline/neural-spark.d.ts +27 -0
  119. package/dist/memory/pipeline/neural-spark.js +78 -0
  120. package/dist/memory/pipeline/skill-prewarm.d.ts +63 -0
  121. package/dist/memory/pipeline/skill-prewarm.js +127 -0
  122. package/dist/memory/pipeline/task-queue.d.ts +54 -0
  123. package/dist/memory/pipeline/task-queue.js +117 -0
  124. package/dist/memory/prompts/cognitive-contradiction.d.ts +1 -0
  125. package/dist/memory/prompts/cognitive-contradiction.js +25 -0
  126. package/dist/memory/prompts/cognitive-extraction.d.ts +10 -0
  127. package/dist/memory/prompts/cognitive-extraction.js +114 -0
  128. package/dist/memory/prompts/core-identity.d.ts +6 -0
  129. package/dist/memory/prompts/core-identity.js +60 -0
  130. package/dist/memory/prompts/focus-direction-shift.d.ts +5 -0
  131. package/dist/memory/prompts/focus-direction-shift.js +32 -0
  132. package/dist/memory/prompts/focus-scene-cluster.d.ts +2 -0
  133. package/dist/memory/prompts/focus-scene-cluster.js +33 -0
  134. package/dist/memory/prompts/focus-scene.d.ts +7 -0
  135. package/dist/memory/prompts/focus-scene.js +40 -0
  136. package/dist/memory/prompts/graph-extraction-batch.d.ts +14 -0
  137. package/dist/memory/prompts/graph-extraction-batch.js +54 -0
  138. package/dist/memory/prompts/graph-extraction.d.ts +2 -0
  139. package/dist/memory/prompts/graph-extraction.js +53 -0
  140. package/dist/memory/prompts/l1-contradiction-batch.d.ts +16 -0
  141. package/dist/memory/prompts/l1-contradiction-batch.js +47 -0
  142. package/dist/memory/prompts/l1-contradiction.d.ts +1 -0
  143. package/dist/memory/prompts/l1-contradiction.js +25 -0
  144. package/dist/memory/prompts/l1-extraction.d.ts +10 -0
  145. package/dist/memory/prompts/l1-extraction.js +114 -0
  146. package/dist/memory/prompts/l2-direction-shift.d.ts +5 -0
  147. package/dist/memory/prompts/l2-direction-shift.js +32 -0
  148. package/dist/memory/prompts/l2-scene-cluster.d.ts +2 -0
  149. package/dist/memory/prompts/l2-scene-cluster.js +33 -0
  150. package/dist/memory/prompts/l2-scene.d.ts +7 -0
  151. package/dist/memory/prompts/l2-scene.js +40 -0
  152. package/dist/memory/prompts/l3-persona.d.ts +6 -0
  153. package/dist/memory/prompts/l3-persona.js +60 -0
  154. package/dist/memory/recall.d.ts +47 -0
  155. package/dist/memory/recall.js +427 -0
  156. package/dist/memory/redaction.d.ts +1 -0
  157. package/dist/memory/redaction.js +24 -0
  158. package/dist/memory/retry.d.ts +13 -0
  159. package/dist/memory/retry.js +53 -0
  160. package/dist/memory/scheduler.d.ts +9 -0
  161. package/dist/memory/scheduler.js +16 -0
  162. package/dist/memory/skill-hints-loader.d.ts +30 -0
  163. package/dist/memory/skill-hints-loader.js +100 -0
  164. package/dist/memory/store/embedding.d.ts +16 -0
  165. package/dist/memory/store/embedding.js +68 -0
  166. package/dist/memory/store/reranker.d.ts +24 -0
  167. package/dist/memory/store/reranker.js +83 -0
  168. package/dist/memory/store/sqlite.d.ts +167 -0
  169. package/dist/memory/store/sqlite.js +1816 -0
  170. package/dist/memory/store/types.d.ts +101 -0
  171. package/dist/memory/store/types.js +1 -0
  172. package/dist/memory/types.d.ts +207 -0
  173. package/dist/memory/types.js +7 -0
  174. package/dist/memory/validation.d.ts +441 -0
  175. package/dist/memory/validation.js +129 -0
  176. package/dist/memory/working/canvas.d.ts +5 -0
  177. package/dist/memory/working/canvas.js +43 -0
  178. package/dist/memory/working/offload.d.ts +71 -0
  179. package/dist/memory/working/offload.js +211 -0
  180. package/dist/memory/working/step-log.d.ts +16 -0
  181. package/dist/memory/working/step-log.js +35 -0
  182. package/dist/registry.d.ts +34 -0
  183. package/dist/registry.js +305 -0
  184. package/dist/resolver.d.ts +17 -0
  185. package/dist/resolver.js +126 -0
  186. package/dist/scripts/validate-foreign-workspace-path.d.ts +1 -0
  187. package/dist/scripts/validate-foreign-workspace-path.js +39 -0
  188. package/dist/tools/agent_memory_tools.d.ts +485 -0
  189. package/dist/tools/agent_memory_tools.js +793 -0
  190. package/dist/tools/create_skill.d.ts +46 -0
  191. package/dist/tools/create_skill.js +46 -0
  192. package/dist/tools/get_doc.d.ts +21 -0
  193. package/dist/tools/get_doc.js +24 -0
  194. package/dist/tools/get_persona.d.ts +15 -0
  195. package/dist/tools/get_persona.js +20 -0
  196. package/dist/tools/get_reference.d.ts +15 -0
  197. package/dist/tools/get_reference.js +20 -0
  198. package/dist/tools/get_skill.d.ts +34 -0
  199. package/dist/tools/get_skill.js +65 -0
  200. package/dist/tools/get_template_doc.d.ts +21 -0
  201. package/dist/tools/get_template_doc.js +24 -0
  202. package/dist/tools/list_docs.d.ts +15 -0
  203. package/dist/tools/list_docs.js +16 -0
  204. package/dist/tools/list_skills.d.ts +18 -0
  205. package/dist/tools/list_skills.js +17 -0
  206. package/dist/tools/list_template_docs.d.ts +15 -0
  207. package/dist/tools/list_template_docs.js +16 -0
  208. package/dist/tools/memory-engineering.d.ts +225 -0
  209. package/dist/tools/memory-engineering.js +284 -0
  210. package/dist/tools/memory-explain.d.ts +34 -0
  211. package/dist/tools/memory-explain.js +109 -0
  212. package/dist/tools/memory-governance.d.ts +171 -0
  213. package/dist/tools/memory-governance.js +224 -0
  214. package/dist/tools/memory-hooks.d.ts +67 -0
  215. package/dist/tools/memory-hooks.js +102 -0
  216. package/dist/tools/memory-working.d.ts +98 -0
  217. package/dist/tools/memory-working.js +101 -0
  218. package/dist/tools/memory_capture_turn.d.ts +66 -0
  219. package/dist/tools/memory_capture_turn.js +85 -0
  220. package/dist/tools/memory_consolidate.d.ts +55 -0
  221. package/dist/tools/memory_consolidate.js +176 -0
  222. package/dist/tools/memory_contradictions.d.ts +53 -0
  223. package/dist/tools/memory_contradictions.js +52 -0
  224. package/dist/tools/memory_graph_query.d.ts +51 -0
  225. package/dist/tools/memory_graph_query.js +35 -0
  226. package/dist/tools/memory_mark_cited.d.ts +43 -0
  227. package/dist/tools/memory_mark_cited.js +63 -0
  228. package/dist/tools/memory_recall.d.ts +77 -0
  229. package/dist/tools/memory_recall.js +81 -0
  230. package/dist/tools/memory_register_skill_hints.d.ts +49 -0
  231. package/dist/tools/memory_register_skill_hints.js +55 -0
  232. package/dist/tools/memory_resolve_session.d.ts +24 -0
  233. package/dist/tools/memory_resolve_session.js +133 -0
  234. package/dist/tools/memory_search.d.ts +146 -0
  235. package/dist/tools/memory_search.js +84 -0
  236. package/dist/tools/search_skills.d.ts +18 -0
  237. package/dist/tools/search_skills.js +17 -0
  238. package/dist/tools/update_doc.d.ts +24 -0
  239. package/dist/tools/update_doc.js +35 -0
  240. package/dist/tools/update_skill.d.ts +30 -0
  241. package/dist/tools/update_skill.js +80 -0
  242. package/dist/types.d.ts +81 -0
  243. package/dist/types.js +4 -0
  244. package/dist/writer.d.ts +30 -0
  245. package/dist/writer.js +220 -0
  246. package/docs/TEMPLATE ONLY +1 -0
  247. package/docs/api/API.md +64 -0
  248. package/docs/api/security/SECURITY.md +58 -0
  249. package/docs/deployment/DockerDeployment.md +30 -0
  250. package/docs/design/Design.md +59 -0
  251. package/docs/design/themes/apple.md +101 -0
  252. package/docs/design/themes/dieter-grid.md +100 -0
  253. package/docs/design/themes/gallery-white.md +100 -0
  254. package/docs/design/themes/pinterest.md +101 -0
  255. package/docs/design/themes/realty-open-house.md +101 -0
  256. package/docs/design/themes/vodafone.md +101 -0
  257. package/docs/hooks/Hooks.md +30 -0
  258. package/docs/schema/Schema.md +35 -0
  259. package/docs/strategy/ScalingStrategy.md +19 -0
  260. package/package.json +88 -0
  261. package/references/accessibility-checklist.md +160 -0
  262. package/references/orchestration-patterns.md +370 -0
  263. package/references/performance-checklist.md +153 -0
  264. package/references/security-checklist.md +134 -0
  265. package/references/testing-patterns.md +236 -0
  266. package/skills/agent/adr-skill/SKILL.md +299 -0
  267. package/skills/agent/agentic-engineering-workflow/SKILL.md +95 -0
  268. package/skills/agent/bootstrap-skill/SKILL.md +103 -0
  269. package/skills/agent/context-engineering/SKILL.md +307 -0
  270. package/skills/agent/debugging-and-error-recovery/SKILL.md +308 -0
  271. package/skills/agent/developer-growth-analysis/SKILL.md +328 -0
  272. package/skills/agent/doubt-driven-skill/SKILL.md +249 -0
  273. package/skills/agent/handover-skill/SKILL.md +112 -0
  274. package/skills/agent/idea-refine-skill/SKILL.md +185 -0
  275. package/skills/agent/idea-refine-skill/examples.md +238 -0
  276. package/skills/agent/idea-refine-skill/frameworks.md +99 -0
  277. package/skills/agent/idea-refine-skill/refinement-criteria.md +113 -0
  278. package/skills/agent/interview-skill/SKILL.md +226 -0
  279. package/skills/agent/planning-skill/SKILL.md +270 -0
  280. package/skills/agent/skill-authoring/SKILL.md +189 -0
  281. package/skills/agent/source-driven-skill/SKILL.md +197 -0
  282. package/skills/agent/spec-driven-skill/SKILL.md +221 -0
  283. package/skills/agent/sync-skill/SKILL.md +92 -0
  284. package/skills/agent/using-agent-skills/SKILL.md +189 -0
  285. package/skills/api/a11y-skill/SKILL.md +88 -0
  286. package/skills/api/api-skill/SKILL.md +123 -0
  287. package/skills/api/auth-skill/SKILL.md +80 -0
  288. package/skills/api/debug-skill/SKILL.md +535 -0
  289. package/skills/api/performance-skill/SKILL.md +100 -0
  290. package/skills/api/testing-skill/SKILL.md +100 -0
  291. package/skills/codebase/code-review-and-quality/SKILL.md +228 -0
  292. package/skills/codebase/code-simplification/SKILL.md +352 -0
  293. package/skills/codebase/code-structure-cleanup/SKILL.md +142 -0
  294. package/skills/codebase/concerns-skill/SKILL.md +89 -0
  295. package/skills/codebase/conventions-skill/SKILL.md +95 -0
  296. package/skills/codebase/doc-management-skill/SKILL.md +47 -0
  297. package/skills/codebase/git-workflow-skill/SKILL.md +312 -0
  298. package/skills/communication/1-3-1-rule/SKILL.md +120 -0
  299. package/skills/design/brutalist-skill/SKILL.md +131 -0
  300. package/skills/design/concept-diagrams/SKILL.md +387 -0
  301. package/skills/design/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
  302. package/skills/design/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
  303. package/skills/design/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
  304. package/skills/design/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
  305. package/skills/design/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
  306. package/skills/design/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
  307. package/skills/design/concept-diagrams/examples/electricity-grid-flow.md +182 -0
  308. package/skills/design/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
  309. package/skills/design/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
  310. package/skills/design/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
  311. package/skills/design/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
  312. package/skills/design/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
  313. package/skills/design/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
  314. package/skills/design/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
  315. package/skills/design/concept-diagrams/examples/wind-turbine-structure.md +338 -0
  316. package/skills/design/concept-diagrams/references/dashboard-patterns.md +43 -0
  317. package/skills/design/concept-diagrams/references/infrastructure-patterns.md +144 -0
  318. package/skills/design/concept-diagrams/references/physical-shape-cookbook.md +42 -0
  319. package/skills/design/concept-diagrams/templates/template.html +174 -0
  320. package/skills/design/gpt-tasteskill/SKILL.md +114 -0
  321. package/skills/design/minimalist-skill/SKILL.md +116 -0
  322. package/skills/design/output-skill/SKILL.md +87 -0
  323. package/skills/design/redesign-skill/SKILL.md +213 -0
  324. package/skills/design/soft-skill/SKILL.md +132 -0
  325. package/skills/design/stitch-skill/EXAMPLE.md +121 -0
  326. package/skills/design/stitch-skill/SKILL.md +222 -0
  327. package/skills/design/taste-skill/SKILL.md +269 -0
  328. package/skills/devops/ci-cd-skill/SKILL.md +402 -0
  329. package/skills/devops/docker-skill/SKILL.md +297 -0
  330. package/skills/devops/domain-skill/SKILL.md +234 -0
  331. package/skills/lifecycle/changelog-generator/SKILL.md +135 -0
  332. package/skills/lifecycle/incremental-skill/SKILL.md +257 -0
  333. package/skills/lifecycle/migration-skill/SKILL.md +218 -0
  334. package/skills/lifecycle/shipping-skill/SKILL.md +321 -0
  335. package/skills/memory/agent-memory/SKILL.md +122 -0
  336. package/skills/qa/browser-testing-skill/SKILL.md +314 -0
  337. package/skills/ux/adversarial-ux-skill/SKILL.md +168 -0
package/dist/index.js ADDED
@@ -0,0 +1,492 @@
1
+ #!/usr/bin/env node
2
+ // ─────────────────────────────────────────────
3
+ // BrainRouter MCP Server — Entry Point
4
+ // ─────────────────────────────────────────────
5
+ //
6
+ // Supports two transport modes:
7
+ //
8
+ // stdio (default)
9
+ // The AI tool spawns this process and communicates via stdin/stdout.
10
+ // No URL, no port. Tool manages the lifecycle.
11
+ // Usage: node dist/index.js --root /path/to/project
12
+ //
13
+ // HTTP (--http flag)
14
+ // Runs an Express HTTP server. Connect via serverUrl in tool config.
15
+ // Usage: node dist/index.js --root /path/to/project --http --port 3747
16
+ //
17
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
18
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
19
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
20
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
21
+ import { randomUUID } from 'node:crypto';
22
+ import express from 'express';
23
+ import { z } from 'zod';
24
+ import fs from "node:fs";
25
+ import { Registry } from './registry.js';
26
+ import { resolveRegistryConfig } from './resolver.js';
27
+ // Import tools
28
+ import { listSkills, listSkillsSchema } from './tools/list_skills.js';
29
+ import { getSkill, getSkillSchema } from './tools/get_skill.js';
30
+ import { searchSkills, searchSkillsSchema } from './tools/search_skills.js';
31
+ import { getPersona, getPersonaSchema } from './tools/get_persona.js';
32
+ import { getReference, getReferenceSchema } from './tools/get_reference.js';
33
+ import { listTemplateDocs, listTemplateDocsSchema } from './tools/list_template_docs.js';
34
+ import { getTemplateDoc, getTemplateDocSchema } from './tools/get_template_doc.js';
35
+ import { createSkill, createSkillSchema } from './tools/create_skill.js';
36
+ import { updateSkill, updateSkillSchema } from './tools/update_skill.js';
37
+ import { memoryCaptureTurnToolSchema, handleMemoryCaptureTurn } from './tools/memory_capture_turn.js';
38
+ import { memoryRecallToolSchema, handleMemoryRecall } from './tools/memory_recall.js';
39
+ import { memorySearchToolSchema, handleMemorySearch } from './tools/memory_search.js';
40
+ import { memoryContradictionsToolSchema, handleMemoryContradictions } from './tools/memory_contradictions.js';
41
+ import { memoryRegisterSkillHintsToolSchema, handleMemoryRegisterSkillHints } from './tools/memory_register_skill_hints.js';
42
+ import { memoryResolveSessionToolSchema, handleMemoryResolveSession } from './tools/memory_resolve_session.js';
43
+ import { memoryGraphQueryToolSchema, handleMemoryGraphQuery } from './tools/memory_graph_query.js';
44
+ import { memoryMarkCitedToolSchema, handleMemoryMarkCited } from './tools/memory_mark_cited.js';
45
+ import { memoryGovernanceToolSchemas, handleMemoryGovernanceTool } from './tools/memory-governance.js';
46
+ import { memoryEngineeringToolSchemas, handleMemoryEngineeringTool } from './tools/memory-engineering.js';
47
+ import { memoryExplainToolSchema, handleMemoryExplainRecall } from './tools/memory-explain.js';
48
+ import { memoryHookToolSchemas, handleMemoryHookTool } from './tools/memory-hooks.js';
49
+ import { memoryWorkingToolSchemas, handleMemoryWorkingTool } from './tools/memory-working.js';
50
+ import { memoryConsolidateToolSchema, handleMemoryConsolidate } from './tools/memory_consolidate.js';
51
+ import { memoryEngine } from './memory/engine.js';
52
+ import path from 'node:path';
53
+ import { usersRouter } from './api/routes/users.js';
54
+ import { memoriesRouter } from './api/routes/memories.js';
55
+ import { scenesRouter } from './api/routes/scenes.js';
56
+ import { personaRouter } from './api/routes/persona.js';
57
+ import { contradictionsRouter } from './api/routes/contradictions.js';
58
+ import { statsRouter } from './api/routes/stats.js';
59
+ import { graphRouter } from './api/routes/graph.js';
60
+ import { authRouter } from './api/routes/auth.js';
61
+ import { chatCompletionsRouter } from './api/routes/chat-completions.js';
62
+ import { governanceRouter } from './api/routes/governance.js';
63
+ import { evidenceRouter } from './api/routes/evidence.js';
64
+ import { hooksRouter } from './api/routes/hooks.js';
65
+ import { workingRouter } from './api/routes/working.js';
66
+ import { skillsRouter } from './api/routes/skills.js';
67
+ import { USING_FALLBACK_JWT_SECRET } from './api/middleware/auth.js';
68
+ const STDIO_DEFAULT_USER_ID = process.env.BRAINROUTER_USER_ID ?? "default";
69
+ const authAttempts = new Map();
70
+ function authRateLimit(req, res, next) {
71
+ const now = Date.now();
72
+ const key = req.ip ?? "unknown";
73
+ const current = authAttempts.get(key);
74
+ const bucket = current && current.resetAt > now ? current : { count: 0, resetAt: now + 15 * 60 * 1000 };
75
+ bucket.count += 1;
76
+ authAttempts.set(key, bucket);
77
+ if (bucket.count > 20) {
78
+ res.status(429).json({ error: "Too many authentication attempts" });
79
+ return;
80
+ }
81
+ next();
82
+ }
83
+ // ─── CLI flags ────────────────────────────────────────────────────────────────
84
+ function parseFlag(flag) {
85
+ const idx = process.argv.indexOf(flag);
86
+ return idx !== -1 && process.argv[idx + 1] ? process.argv[idx + 1] : undefined;
87
+ }
88
+ const USE_HTTP = process.argv.includes('--http');
89
+ const PORT = parseInt(parseFlag('--port') ?? '3747', 10);
90
+ // ─── Server factory ───────────────────────────────────────────────────────────
91
+ function buildMcpServer(registry, options) {
92
+ const defaultUserId = options?.defaultUserId ?? STDIO_DEFAULT_USER_ID;
93
+ const isAdmin = options?.isAdmin ?? false;
94
+ const server = new Server({ name: 'brainrouter-mcp-server', version: '0.3.4' }, { capabilities: { tools: {} } });
95
+ // ── Tool list ──────────────────────────────────────────────────────────────
96
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
97
+ tools: [
98
+ {
99
+ name: 'list_skills',
100
+ description: 'List all available skills (global + local merged).',
101
+ inputSchema: {
102
+ type: 'object',
103
+ properties: {
104
+ category: { type: 'string', description: 'Filter by category folder' },
105
+ scope: { type: 'string', enum: ['global', 'local', 'all'], description: 'Filter by scope' },
106
+ },
107
+ },
108
+ },
109
+ {
110
+ name: 'get_skill',
111
+ description: 'Fetch a specific section of a skill (default: workflow) or read an auxiliary file within the skill directory.',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ name: { type: 'string', description: 'kebab-case skill name' },
116
+ section: {
117
+ type: 'string',
118
+ enum: [
119
+ 'description', 'overview', 'when_to_use', 'workflow', 'usage',
120
+ 'detailed_instructions', 'phases', 'checklist', 'red_flags',
121
+ 'rationalizations', 'full',
122
+ ],
123
+ description: 'Section to load',
124
+ },
125
+ file: { type: 'string', description: 'Optional filename to read instead of a section (e.g. "examples.md")' },
126
+ },
127
+ required: ['name'],
128
+ },
129
+ },
130
+ {
131
+ name: 'search_skills',
132
+ description: 'Fuzzy search across all skills.',
133
+ inputSchema: {
134
+ type: 'object',
135
+ properties: {
136
+ query: { type: 'string', description: 'Keyword to search for' },
137
+ scope: { type: 'string', enum: ['global', 'local', 'all'] },
138
+ },
139
+ required: ['query'],
140
+ },
141
+ },
142
+ {
143
+ name: 'get_persona',
144
+ description: 'Fetch a persona definition.',
145
+ inputSchema: {
146
+ type: 'object',
147
+ properties: {
148
+ name: { type: 'string', description: 'Persona name (e.g. code-reviewer)' },
149
+ },
150
+ required: ['name'],
151
+ },
152
+ },
153
+ {
154
+ name: 'get_reference',
155
+ description: 'Fetch a reference document.',
156
+ inputSchema: {
157
+ type: 'object',
158
+ properties: {
159
+ name: { type: 'string', description: 'Reference name (e.g. security-checklist)' },
160
+ },
161
+ required: ['name'],
162
+ },
163
+ },
164
+ {
165
+ name: 'list_template_docs',
166
+ description: 'List all project-specific template documentation.',
167
+ inputSchema: {
168
+ type: 'object',
169
+ properties: {
170
+ category: { type: 'string', enum: ['api', 'design', 'schema', 'deployment', 'hooks', 'strategy', 'other'] },
171
+ },
172
+ },
173
+ },
174
+ {
175
+ name: 'get_template_doc',
176
+ description: 'Read a project template document or section.',
177
+ inputSchema: {
178
+ type: 'object',
179
+ properties: {
180
+ name: { type: 'string', description: 'Doc name (e.g. api, design)' },
181
+ section: { type: 'string', description: '## heading to load' },
182
+ },
183
+ required: ['name'],
184
+ },
185
+ },
186
+ {
187
+ name: 'create_skill',
188
+ description: 'Scaffold a new skill. If scope is "global", ensure content is universal (replace project-specific terms like "YourProject" with generic ones like "the project") UNLESS the category is a project name.',
189
+ inputSchema: {
190
+ type: 'object',
191
+ properties: {
192
+ name: { type: 'string' },
193
+ category: { type: 'string' },
194
+ description: { type: 'string' },
195
+ overview: { type: 'string' },
196
+ when_to_use: { type: 'string' },
197
+ workflow: { type: 'array', items: { type: 'string' } },
198
+ usage: { type: 'string' },
199
+ checklist: { type: 'array', items: { type: 'string' } },
200
+ scope: { type: 'string', enum: ['global', 'local'], description: 'Where to save: "local" (default) or "global" (BrainRouter repo)' },
201
+ project: { type: 'string', description: 'Optional project name for project-specific skills (e.g. "YourProject")' },
202
+ },
203
+ required: ['name', 'category', 'description'],
204
+ },
205
+ },
206
+ {
207
+ name: 'update_skill',
208
+ description: 'Update an existing skill section. Supports "shadowing" global skills locally or updating global skills directly.',
209
+ inputSchema: {
210
+ type: 'object',
211
+ properties: {
212
+ name: { type: 'string' },
213
+ section: { type: 'string', enum: ['overview', 'workflow', 'usage', 'detailed_instructions', 'checklist', 'full'] },
214
+ content: { type: 'string' },
215
+ targetScope: { type: 'string', enum: ['global', 'local'], description: 'Override where to save the update' },
216
+ project: { type: 'string', description: 'Optional project name if elevating to global' },
217
+ },
218
+ required: ['name', 'section', 'content'],
219
+ },
220
+ },
221
+ memoryCaptureTurnToolSchema,
222
+ memoryRecallToolSchema,
223
+ memorySearchToolSchema,
224
+ memoryContradictionsToolSchema,
225
+ memoryRegisterSkillHintsToolSchema,
226
+ memoryResolveSessionToolSchema,
227
+ memoryGraphQueryToolSchema,
228
+ memoryMarkCitedToolSchema,
229
+ ...memoryGovernanceToolSchemas,
230
+ ...memoryEngineeringToolSchemas,
231
+ memoryExplainToolSchema,
232
+ ...memoryHookToolSchemas,
233
+ ...memoryWorkingToolSchemas,
234
+ memoryConsolidateToolSchema,
235
+ ],
236
+ }));
237
+ // ── Tool dispatcher ────────────────────────────────────────────────────────
238
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
239
+ try {
240
+ switch (request.params.name) {
241
+ case 'list_skills': return await listSkills(registry, listSkillsSchema.parse(request.params.arguments));
242
+ case 'get_skill': return await getSkill(registry, getSkillSchema.parse(request.params.arguments));
243
+ case 'search_skills': return await searchSkills(registry, searchSkillsSchema.parse(request.params.arguments));
244
+ case 'get_persona': return await getPersona(registry, getPersonaSchema.parse(request.params.arguments));
245
+ case 'get_reference': return await getReference(registry, getReferenceSchema.parse(request.params.arguments));
246
+ case 'list_template_docs': return await listTemplateDocs(registry, listTemplateDocsSchema.parse(request.params.arguments));
247
+ case 'get_template_doc': return await getTemplateDoc(registry, getTemplateDocSchema.parse(request.params.arguments));
248
+ case 'create_skill':
249
+ case 'update_skill':
250
+ if (!isAdmin) {
251
+ throw new McpError(ErrorCode.InvalidRequest, 'Admin access required for this tool');
252
+ }
253
+ if (request.params.name === "create_skill") {
254
+ return await createSkill(registry, createSkillSchema.parse(request.params.arguments));
255
+ }
256
+ return await updateSkill(registry, updateSkillSchema.parse(request.params.arguments));
257
+ case 'memory_capture_turn': return await handleMemoryCaptureTurn(request.params.arguments, { defaultUserId });
258
+ case 'memory_recall': return await handleMemoryRecall(request.params.arguments, { defaultUserId });
259
+ case 'memory_search': return await handleMemorySearch(request.params.arguments, { defaultUserId });
260
+ case 'memory_contradictions': return await handleMemoryContradictions(request.params.arguments, { defaultUserId });
261
+ case 'memory_register_skill_hints': return await handleMemoryRegisterSkillHints(request.params.arguments);
262
+ case 'memory_resolve_session': return await handleMemoryResolveSession(request.params.arguments);
263
+ case 'memory_graph_query': return await handleMemoryGraphQuery(request.params.arguments, { defaultUserId });
264
+ case 'memory_mark_cited': return await handleMemoryMarkCited(request.params.arguments, { defaultUserId });
265
+ case 'memory_get':
266
+ case 'memory_update':
267
+ case 'memory_evidence_add':
268
+ case 'memory_evidence_get':
269
+ case 'memory_export':
270
+ case 'memory_import':
271
+ case 'memory_governance_delete':
272
+ case 'memory_audit':
273
+ case 'memory_diagnostics':
274
+ return await handleMemoryGovernanceTool(request.params.name, request.params.arguments, { defaultUserId });
275
+ case 'memory_debug_trace_save':
276
+ case 'memory_debug_trace_search':
277
+ case 'memory_failed_attempts':
278
+ case 'memory_file_history':
279
+ case 'memory_task_state':
280
+ case 'memory_task_update':
281
+ case 'memory_handover':
282
+ case 'memory_verify':
283
+ return await handleMemoryEngineeringTool(request.params.name, request.params.arguments, { defaultUserId });
284
+ case 'memory_explain_recall':
285
+ return await handleMemoryExplainRecall(request.params.arguments, { defaultUserId });
286
+ case 'memory_hook_register':
287
+ case 'memory_hook_status':
288
+ return await handleMemoryHookTool(request.params.name, request.params.arguments, { defaultUserId });
289
+ case 'memory_working_context':
290
+ case 'memory_working_offload':
291
+ case 'memory_working_reset':
292
+ return await handleMemoryWorkingTool(request.params.name, request.params.arguments, { defaultUserId });
293
+ case 'memory_consolidate':
294
+ return await handleMemoryConsolidate(request.params.arguments, { defaultUserId });
295
+ default:
296
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
297
+ }
298
+ }
299
+ catch (error) {
300
+ if (error instanceof z.ZodError) {
301
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments: ${error.errors.map(e => e.message).join(', ')}`);
302
+ }
303
+ throw error;
304
+ }
305
+ });
306
+ server.onerror = (error) => console.error('[MCP Error]', error);
307
+ return server;
308
+ }
309
+ // ─── Bootstrap ────────────────────────────────────────────────────────────────
310
+ const config = resolveRegistryConfig();
311
+ const registry = new Registry(config);
312
+ registry.build();
313
+ // Auto-scan skills dirs for memory_hints on startup
314
+ const skillsDirsToScan = [
315
+ path.join(config.globalRoot, 'skills'),
316
+ config.localRoot ? path.join(config.localRoot, 'skills') : undefined,
317
+ ].filter((d) => !!d); // remove undefined and deduplicate
318
+ const uniqueSkillsDirs = [...new Set(skillsDirsToScan)];
319
+ memoryEngine.autoScanSkillHints(uniqueSkillsDirs);
320
+ if (USE_HTTP) {
321
+ // ── HTTP / Streamable-HTTP transport ────────────────────────────────────────
322
+ // Each client session gets its own Server + Transport instance.
323
+ const sessions = new Map();
324
+ const app = express();
325
+ // Custom CORS middleware to support cross-origin requests from Dashboard
326
+ app.use((req, res, next) => {
327
+ const allowedOrigin = process.env.BRAINROUTER_CORS_ORIGIN || "http://localhost:3000";
328
+ const requestOrigin = req.headers.origin;
329
+ if (!requestOrigin || requestOrigin === allowedOrigin) {
330
+ res.setHeader("Access-Control-Allow-Origin", requestOrigin ?? allowedOrigin);
331
+ }
332
+ res.setHeader("Vary", "Origin");
333
+ res.setHeader("Access-Control-Allow-Credentials", "true");
334
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
335
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, mcp-session-id");
336
+ if (req.method === "OPTIONS") {
337
+ res.sendStatus(200);
338
+ return;
339
+ }
340
+ next();
341
+ });
342
+ app.use(express.json());
343
+ if (USING_FALLBACK_JWT_SECRET) {
344
+ console.error("[BrainRouter] WARNING: running with generated JWT secret. Set BRAINROUTER_JWT_SECRET in production.");
345
+ }
346
+ // Health check
347
+ app.get('/health', (_req, res) => {
348
+ res.json({ status: 'ok', transport: 'http', root: config.localRoot });
349
+ });
350
+ app.use("/api/auth/signin", authRateLimit);
351
+ app.use("/api/auth/signup", authRateLimit);
352
+ app.use("/api/auth", authRouter);
353
+ app.use("/api/users", usersRouter);
354
+ app.use("/api/memories", memoriesRouter);
355
+ app.use("/api/scenes", scenesRouter);
356
+ app.use("/api/persona", personaRouter);
357
+ app.use("/api/contradictions", contradictionsRouter);
358
+ app.use("/api/stats", statsRouter);
359
+ app.use("/api/graph", graphRouter);
360
+ app.use("/api", governanceRouter);
361
+ app.use("/api/evidence", evidenceRouter);
362
+ app.use("/api/hooks", hooksRouter);
363
+ app.use("/api/working", workingRouter);
364
+ app.use("/api/skills", skillsRouter);
365
+ // OpenAI-compatible chat endpoint (memory-augmented):
366
+ // POST /v1/chat/completions — standard OpenAI body, sessionKey via body.brainrouter.sessionKey or X-BrainRouter-Session header
367
+ // GET /v1/models — returns the configured upstream model
368
+ app.use("/v1", chatCompletionsRouter);
369
+ // MCP endpoint — handles POST (requests) and GET (SSE stream)
370
+ async function handleMcp(req, res) {
371
+ const sessionId = req.headers['mcp-session-id'];
372
+ const authHeader = req.headers.authorization;
373
+ const bearerKey = authHeader?.startsWith("Bearer ") ? authHeader.slice(7).trim() : "";
374
+ if (!bearerKey) {
375
+ res.status(401).json({ error: 'API key required. Set Authorization: Bearer <your_api_key>' });
376
+ return;
377
+ }
378
+ const user = memoryEngine.getUserByApiKey(bearerKey);
379
+ if (!user) {
380
+ res.status(403).json({ error: 'Invalid API key' });
381
+ return;
382
+ }
383
+ if (user.status === "disabled") {
384
+ res.status(403).json({ error: "Account disabled" });
385
+ return;
386
+ }
387
+ const effectiveUserId = user.userId;
388
+ if (req.method === 'POST' && !sessionId) {
389
+ // New session — initialise
390
+ const transport = new StreamableHTTPServerTransport({
391
+ sessionIdGenerator: () => randomUUID(),
392
+ onsessioninitialized: (id) => {
393
+ sessions.set(id, { server: mcpServer, transport });
394
+ },
395
+ });
396
+ const mcpServer = buildMcpServer(registry, { defaultUserId: effectiveUserId, isAdmin: user.isAdmin });
397
+ transport.onclose = () => {
398
+ const id = [...sessions.entries()].find(([, v]) => v.transport === transport)?.[0];
399
+ if (id)
400
+ sessions.delete(id);
401
+ };
402
+ await mcpServer.connect(transport);
403
+ await transport.handleRequest(req, res, req.body);
404
+ return;
405
+ }
406
+ // Existing session
407
+ const session = sessionId ? sessions.get(sessionId) : undefined;
408
+ if (!session) {
409
+ res.status(404).json({ error: 'Session not found. Send a POST without mcp-session-id to initialise.' });
410
+ return;
411
+ }
412
+ await session.transport.handleRequest(req, res, req.body);
413
+ }
414
+ app.post('/mcp', handleMcp);
415
+ app.get('/mcp', handleMcp);
416
+ // DELETE — client-side session teardown
417
+ app.delete('/mcp', (req, res) => {
418
+ const sessionId = req.headers['mcp-session-id'];
419
+ if (sessionId)
420
+ sessions.delete(sessionId);
421
+ res.status(204).send();
422
+ });
423
+ const dashboardDist = path.resolve(process.cwd(), "..", "dashboard", "dist");
424
+ if (fs.existsSync(dashboardDist)) {
425
+ app.use("/dashboard", express.static(dashboardDist));
426
+ app.get("/dashboard/*", (_req, res) => {
427
+ res.sendFile(path.join(dashboardDist, "index.html"));
428
+ });
429
+ }
430
+ const httpServer = app.listen(PORT, () => {
431
+ console.log(`\n🧠 BrainRouter MCP Server`);
432
+ console.log(` Transport : HTTP (Streamable)`);
433
+ console.log(` Endpoint : http://localhost:${PORT}/mcp`);
434
+ console.log(` Health : http://localhost:${PORT}/health`);
435
+ console.log(` Root : ${config.localRoot}\n`);
436
+ });
437
+ process.on('SIGINT', () => {
438
+ httpServer.close(() => process.exit(0));
439
+ });
440
+ }
441
+ else {
442
+ // ── stdio transport (default) ───────────────────────────────────────────────
443
+ // Redirect console.log and console.warn to stderr to avoid polluting stdout.
444
+ // In stdio mode, stdout is strictly reserved for the MCP protocol.
445
+ console.log = (...args) => console.error(...args);
446
+ console.warn = (...args) => console.error(...args);
447
+ // Authenticate user via environment variable or CLI flag
448
+ let stdioUserId = "";
449
+ let stdioIsAdmin = false;
450
+ const stdioApiKey = (process.env.BRAINROUTER_API_KEY ?? parseFlag('--apiKey'))?.trim();
451
+ if (!stdioApiKey) {
452
+ console.error("[BrainRouter] FATAL: Connection aborted. Authentication is strictly required for all tool operations.");
453
+ console.error("[BrainRouter] To fix this, please configure BRAINROUTER_API_KEY inside your MCP client config environment variables.");
454
+ console.error("[BrainRouter] Example configuration:");
455
+ console.error(JSON.stringify({
456
+ mcpServers: {
457
+ brainrouter: {
458
+ command: "node",
459
+ args: [
460
+ "/absolute/path/to/BrainRouter/brainrouter/dist/index.js",
461
+ "--root",
462
+ "/absolute/path/to/your/workspace"
463
+ ],
464
+ env: {
465
+ BRAINROUTER_API_KEY: "br_YOUR_API_KEY"
466
+ }
467
+ }
468
+ }
469
+ }, null, 2));
470
+ process.exit(1);
471
+ }
472
+ const user = memoryEngine.getUserByApiKey(stdioApiKey);
473
+ if (!user) {
474
+ console.error("[BrainRouter] FATAL: The provided BRAINROUTER_API_KEY is invalid. Connection aborted.");
475
+ process.exit(1);
476
+ }
477
+ if (user.status === "disabled") {
478
+ console.error("[BrainRouter] FATAL: The provided BRAINROUTER_API_KEY belongs to a disabled account.");
479
+ process.exit(1);
480
+ }
481
+ stdioUserId = user.userId;
482
+ stdioIsAdmin = user.isAdmin;
483
+ console.error(`[BrainRouter] Authenticated via BRAINROUTER_API_KEY. Mapping local session to user: ${user.displayName || user.userId}`);
484
+ const server = buildMcpServer(registry, { defaultUserId: stdioUserId, isAdmin: stdioIsAdmin });
485
+ const transport = new StdioServerTransport();
486
+ await server.connect(transport);
487
+ console.error('BrainRouter MCP server running on stdio');
488
+ process.on('SIGINT', async () => {
489
+ await server.close();
490
+ process.exit(0);
491
+ });
492
+ }
@@ -0,0 +1,12 @@
1
+ import { type HostHookEvent } from "./generic-mcp.js";
2
+ import type { MemoryEngine } from "../memory/engine.js";
3
+ declare const CLAUDE_CODE_EVENTS: readonly ["PreToolUse", "PostToolUse", "Stop", "SubagentStop"];
4
+ export type ClaudeCodeHookEventName = typeof CLAUDE_CODE_EVENTS[number];
5
+ export declare function normalizeClaudeCodeHook(raw: Record<string, unknown>, defaultUserId: string): HostHookEvent;
6
+ export declare function processClaudeCodeHook(engine: Pick<MemoryEngine, "capturePassiveL0">, raw: Record<string, unknown>, defaultUserId: string): Promise<{
7
+ hookId: string;
8
+ l0RecordedCount: number;
9
+ l0RecordId: string;
10
+ flushedWorkingMemory: boolean;
11
+ }>;
12
+ export {};
@@ -0,0 +1,35 @@
1
+ import { fallbackSessionKey, processGenericMcpHook, } from "./generic-mcp.js";
2
+ const CLAUDE_CODE_EVENTS = ["PreToolUse", "PostToolUse", "Stop", "SubagentStop"];
3
+ function parseEventName(value) {
4
+ const eventName = String(value || "");
5
+ return CLAUDE_CODE_EVENTS.includes(eventName)
6
+ ? eventName
7
+ : "PostToolUse";
8
+ }
9
+ export function normalizeClaudeCodeHook(raw, defaultUserId) {
10
+ const event = parseEventName(raw.event ?? raw.hook_event_name ?? raw.hookEventName);
11
+ const sessionKey = String(raw.sessionKey
12
+ ?? raw.session_key
13
+ ?? raw.session_id
14
+ ?? raw.transcript_path
15
+ ?? fallbackSessionKey("claude-code"));
16
+ return {
17
+ source: "claude-code",
18
+ event,
19
+ userId: String(raw.userId ?? raw.user_id ?? defaultUserId),
20
+ sessionKey,
21
+ sessionId: raw.sessionId || raw.session_id ? String(raw.sessionId ?? raw.session_id) : undefined,
22
+ workspacePath: raw.workspacePath || raw.cwd ? String(raw.workspacePath ?? raw.cwd) : undefined,
23
+ toolName: raw.toolName || raw.tool_name ? String(raw.toolName ?? raw.tool_name) : undefined,
24
+ args: raw.args ?? raw.tool_input ?? raw.input,
25
+ result: raw.result ?? raw.tool_response ?? raw.output,
26
+ metadata: {
27
+ transcriptPath: raw.transcript_path,
28
+ rawEvent: event,
29
+ },
30
+ timestamp: typeof raw.timestamp === "number" ? raw.timestamp : Date.now(),
31
+ };
32
+ }
33
+ export async function processClaudeCodeHook(engine, raw, defaultUserId) {
34
+ return processGenericMcpHook(engine, normalizeClaudeCodeHook(raw, defaultUserId));
35
+ }
@@ -0,0 +1,12 @@
1
+ import { type HostHookEvent } from "./generic-mcp.js";
2
+ import type { MemoryEngine } from "../memory/engine.js";
3
+ declare const CODEX_EVENTS: readonly ["session_start", "session_end", "prompt_submit", "compact"];
4
+ export type CodexHookEventName = typeof CODEX_EVENTS[number];
5
+ export declare function normalizeCodexHook(raw: Record<string, unknown>, defaultUserId: string): HostHookEvent;
6
+ export declare function processCodexHook(engine: Pick<MemoryEngine, "capturePassiveL0">, raw: Record<string, unknown>, defaultUserId: string): Promise<{
7
+ hookId: string;
8
+ l0RecordedCount: number;
9
+ l0RecordId: string;
10
+ flushedWorkingMemory: boolean;
11
+ }>;
12
+ export {};
@@ -0,0 +1,34 @@
1
+ import { fallbackSessionKey, processGenericMcpHook, } from "./generic-mcp.js";
2
+ const CODEX_EVENTS = ["session_start", "session_end", "prompt_submit", "compact"];
3
+ function parseEventName(value) {
4
+ const eventName = String(value || "");
5
+ return CODEX_EVENTS.includes(eventName)
6
+ ? eventName
7
+ : "prompt_submit";
8
+ }
9
+ export function normalizeCodexHook(raw, defaultUserId) {
10
+ const event = parseEventName(raw.event ?? raw.hookEventName ?? raw.hook_event_name);
11
+ const sessionKey = String(raw.sessionKey
12
+ ?? raw.session_key
13
+ ?? raw.conversationId
14
+ ?? raw.conversation_id
15
+ ?? fallbackSessionKey("codex"));
16
+ return {
17
+ source: "codex",
18
+ event,
19
+ userId: String(raw.userId ?? raw.user_id ?? defaultUserId),
20
+ sessionKey,
21
+ sessionId: raw.sessionId || raw.session_id ? String(raw.sessionId ?? raw.session_id) : undefined,
22
+ workspacePath: raw.workspacePath || raw.cwd ? String(raw.workspacePath ?? raw.cwd) : undefined,
23
+ prompt: raw.prompt ? String(raw.prompt) : undefined,
24
+ content: raw.content ? String(raw.content) : undefined,
25
+ metadata: {
26
+ compactReason: raw.compactReason ?? raw.compact_reason,
27
+ rawEvent: event,
28
+ },
29
+ timestamp: typeof raw.timestamp === "number" ? raw.timestamp : Date.now(),
30
+ };
31
+ }
32
+ export async function processCodexHook(engine, raw, defaultUserId) {
33
+ return processGenericMcpHook(engine, normalizeCodexHook(raw, defaultUserId));
34
+ }
@@ -0,0 +1,52 @@
1
+ import type { MemoryEngine } from "../memory/engine.js";
2
+ export type HostHookSource = "claude-code" | "codex" | "generic-mcp" | string;
3
+ export interface HostHookEvent {
4
+ source: HostHookSource;
5
+ event: string;
6
+ userId: string;
7
+ sessionKey: string;
8
+ sessionId?: string;
9
+ workspacePath?: string;
10
+ toolName?: string;
11
+ args?: unknown;
12
+ result?: unknown;
13
+ prompt?: string;
14
+ content?: string;
15
+ metadata?: Record<string, unknown>;
16
+ timestamp?: number;
17
+ }
18
+ export interface RegisteredHook {
19
+ id: string;
20
+ userId: string;
21
+ source: HostHookSource;
22
+ events: string[];
23
+ sessionKey?: string;
24
+ workspacePath?: string;
25
+ registeredAt: string;
26
+ lastSeenAt: string | null;
27
+ lastEvent: string | null;
28
+ metadata: Record<string, unknown>;
29
+ }
30
+ export declare function sanitizeHookPayload(value: unknown, depth?: number): unknown;
31
+ export declare function registerHostHook(params: {
32
+ userId: string;
33
+ source: HostHookSource;
34
+ events?: string[];
35
+ sessionKey?: string;
36
+ workspacePath?: string;
37
+ metadata?: Record<string, unknown>;
38
+ }): RegisteredHook;
39
+ export declare function listHostHooks(userId: string): RegisteredHook[];
40
+ export declare function processGenericMcpHook(engine: Pick<MemoryEngine, "capturePassiveL0">, event: HostHookEvent): Promise<{
41
+ hookId: string;
42
+ l0RecordedCount: number;
43
+ l0RecordId: string;
44
+ flushedWorkingMemory: boolean;
45
+ }>;
46
+ export declare function buildHookResult(value: unknown): {
47
+ content: {
48
+ type: string;
49
+ text: string;
50
+ }[];
51
+ };
52
+ export declare function fallbackSessionKey(source: HostHookSource): string;