memento-mcp-server 0.1.0

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 (555) hide show
  1. package/.cursor/rules/cache-management.mdc +171 -0
  2. package/.cursor/rules/database-schema.mdc +344 -0
  3. package/.cursor/rules/deployment.mdc +596 -0
  4. package/.cursor/rules/error-logging.mdc +298 -0
  5. package/.cursor/rules/forgetting-algorithms.mdc +426 -0
  6. package/.cursor/rules/http-server.mdc +432 -0
  7. package/.cursor/rules/hybrid-search.mdc +424 -0
  8. package/.cursor/rules/implementation.mdc +369 -0
  9. package/.cursor/rules/lightweight-embedding.mdc +178 -0
  10. package/.cursor/rules/mcp-client-development.mdc +0 -0
  11. package/.cursor/rules/mcp-server-development.mdc +0 -0
  12. package/.cursor/rules/mcp-tools-architecture.mdc +205 -0
  13. package/.cursor/rules/memento-memory-rule.mdc +8 -0
  14. package/.cursor/rules/memento-project-overview.mdc +0 -0
  15. package/.cursor/rules/memory-algorithms.mdc +502 -0
  16. package/.cursor/rules/monitoring.mdc +622 -0
  17. package/.cursor/rules/performance-alerts.mdc +537 -0
  18. package/.cursor/rules/performance-monitoring.mdc +345 -0
  19. package/.cursor/rules/performance-optimization.mdc +563 -0
  20. package/.cursor/rules/project-structure.mdc +310 -0
  21. package/.cursor/rules/testing.mdc +473 -0
  22. package/.dockerignore +15 -0
  23. package/.eslintrc.json +34 -0
  24. package/.github/ISSUE_TEMPLATE/bug_report.md +51 -0
  25. package/.github/ISSUE_TEMPLATE/feature_request.md +45 -0
  26. package/.github/ISSUE_TEMPLATE/question.md +31 -0
  27. package/.github/PULL_REQUEST_TEMPLATE.md +97 -0
  28. package/AGENTS.md +28 -0
  29. package/CHANGELOG.md +416 -0
  30. package/CODE_OF_CONDUCT.md +62 -0
  31. package/CONTRIBUTING.md +165 -0
  32. package/DOCKER_SETUP_GUIDE.md +84 -0
  33. package/Dockerfile +90 -0
  34. package/INSTALL.en.md +303 -0
  35. package/INSTALL.md +303 -0
  36. package/README.en.md +330 -0
  37. package/README.md +427 -0
  38. package/backup/legacy-removal-20250930-201816/http-server-legacy.ts +1068 -0
  39. package/backup/legacy-removal-20250930-201816/rollback-to-legacy.ps1 +46 -0
  40. package/backup/legacy-removal-20250930-201816/rollback-to-legacy.sh +48 -0
  41. package/dist/algorithms/forgetting-algorithm.d.ts +90 -0
  42. package/dist/algorithms/forgetting-algorithm.d.ts.map +1 -0
  43. package/dist/algorithms/forgetting-algorithm.js +160 -0
  44. package/dist/algorithms/forgetting-algorithm.js.map +1 -0
  45. package/dist/algorithms/hybrid-search-engine.d.ts +108 -0
  46. package/dist/algorithms/hybrid-search-engine.d.ts.map +1 -0
  47. package/dist/algorithms/hybrid-search-engine.js +384 -0
  48. package/dist/algorithms/hybrid-search-engine.js.map +1 -0
  49. package/dist/algorithms/search-engine.d.ts +64 -0
  50. package/dist/algorithms/search-engine.d.ts.map +1 -0
  51. package/dist/algorithms/search-engine.js +304 -0
  52. package/dist/algorithms/search-engine.js.map +1 -0
  53. package/dist/algorithms/search-ranking.d.ts +145 -0
  54. package/dist/algorithms/search-ranking.d.ts.map +1 -0
  55. package/dist/algorithms/search-ranking.js +311 -0
  56. package/dist/algorithms/search-ranking.js.map +1 -0
  57. package/dist/algorithms/spaced-repetition.d.ts +83 -0
  58. package/dist/algorithms/spaced-repetition.d.ts.map +1 -0
  59. package/dist/algorithms/spaced-repetition.js +153 -0
  60. package/dist/algorithms/spaced-repetition.js.map +1 -0
  61. package/dist/algorithms/vector-search-engine.d.ts +96 -0
  62. package/dist/algorithms/vector-search-engine.d.ts.map +1 -0
  63. package/dist/algorithms/vector-search-engine.js +410 -0
  64. package/dist/algorithms/vector-search-engine.js.map +1 -0
  65. package/dist/client/index.d.ts +55 -0
  66. package/dist/client/index.d.ts.map +1 -0
  67. package/dist/client/index.js +179 -0
  68. package/dist/client/index.js.map +1 -0
  69. package/dist/config/index.d.ts +20 -0
  70. package/dist/config/index.d.ts.map +1 -0
  71. package/dist/config/index.js +87 -0
  72. package/dist/config/index.js.map +1 -0
  73. package/dist/database/init.d.ts +7 -0
  74. package/dist/database/init.d.ts.map +1 -0
  75. package/dist/database/init.js +117 -0
  76. package/dist/database/init.js.map +1 -0
  77. package/dist/database/migrate.d.ts +6 -0
  78. package/dist/database/migrate.d.ts.map +1 -0
  79. package/dist/database/migrate.js +84 -0
  80. package/dist/database/migrate.js.map +1 -0
  81. package/dist/database/schema.sql +159 -0
  82. package/dist/npm-client/context-injector.d.ts +106 -0
  83. package/dist/npm-client/context-injector.d.ts.map +1 -0
  84. package/dist/npm-client/context-injector.js +296 -0
  85. package/dist/npm-client/context-injector.js.map +1 -0
  86. package/dist/npm-client/index.d.ts +42 -0
  87. package/dist/npm-client/index.d.ts.map +1 -0
  88. package/dist/npm-client/index.js +43 -0
  89. package/dist/npm-client/index.js.map +1 -0
  90. package/dist/npm-client/memento-client.d.ts +114 -0
  91. package/dist/npm-client/memento-client.d.ts.map +1 -0
  92. package/dist/npm-client/memento-client.js +391 -0
  93. package/dist/npm-client/memento-client.js.map +1 -0
  94. package/dist/npm-client/memory-manager.d.ts +137 -0
  95. package/dist/npm-client/memory-manager.d.ts.map +1 -0
  96. package/dist/npm-client/memory-manager.js +341 -0
  97. package/dist/npm-client/memory-manager.js.map +1 -0
  98. package/dist/npm-client/types.d.ts +216 -0
  99. package/dist/npm-client/types.d.ts.map +1 -0
  100. package/dist/npm-client/types.js +44 -0
  101. package/dist/npm-client/types.js.map +1 -0
  102. package/dist/npm-client/utils.d.ts +91 -0
  103. package/dist/npm-client/utils.d.ts.map +1 -0
  104. package/dist/npm-client/utils.js +351 -0
  105. package/dist/npm-client/utils.js.map +1 -0
  106. package/dist/scripts/copy-assets.d.ts +3 -0
  107. package/dist/scripts/copy-assets.d.ts.map +1 -0
  108. package/dist/scripts/copy-assets.js +31 -0
  109. package/dist/scripts/copy-assets.js.map +1 -0
  110. package/dist/server/http-server.d.ts +28 -0
  111. package/dist/server/http-server.d.ts.map +1 -0
  112. package/dist/server/http-server.js +930 -0
  113. package/dist/server/http-server.js.map +1 -0
  114. package/dist/server/index-backup.d.ts +5 -0
  115. package/dist/server/index-backup.d.ts.map +1 -0
  116. package/dist/server/index-backup.js +793 -0
  117. package/dist/server/index-backup.js.map +1 -0
  118. package/dist/server/index-refactored.d.ts +6 -0
  119. package/dist/server/index-refactored.d.ts.map +1 -0
  120. package/dist/server/index-refactored.js +206 -0
  121. package/dist/server/index-refactored.js.map +1 -0
  122. package/dist/server/index.d.ts +12 -0
  123. package/dist/server/index.d.ts.map +1 -0
  124. package/dist/server/index.js +301 -0
  125. package/dist/server/index.js.map +1 -0
  126. package/dist/server/simple-mcp-server.d.ts +8 -0
  127. package/dist/server/simple-mcp-server.d.ts.map +1 -0
  128. package/dist/server/simple-mcp-server.js +152 -0
  129. package/dist/server/simple-mcp-server.js.map +1 -0
  130. package/dist/services/async-optimizer.d.ts +136 -0
  131. package/dist/services/async-optimizer.d.ts.map +1 -0
  132. package/dist/services/async-optimizer.js +406 -0
  133. package/dist/services/async-optimizer.js.map +1 -0
  134. package/dist/services/batch-scheduler.d.ts +156 -0
  135. package/dist/services/batch-scheduler.d.ts.map +1 -0
  136. package/dist/services/batch-scheduler.js +612 -0
  137. package/dist/services/batch-scheduler.js.map +1 -0
  138. package/dist/services/cache-service.d.ts +168 -0
  139. package/dist/services/cache-service.d.ts.map +1 -0
  140. package/dist/services/cache-service.js +360 -0
  141. package/dist/services/cache-service.js.map +1 -0
  142. package/dist/services/database-optimizer.d.ts +110 -0
  143. package/dist/services/database-optimizer.d.ts.map +1 -0
  144. package/dist/services/database-optimizer.js +369 -0
  145. package/dist/services/database-optimizer.js.map +1 -0
  146. package/dist/services/embedding-provider-factory.d.ts +62 -0
  147. package/dist/services/embedding-provider-factory.d.ts.map +1 -0
  148. package/dist/services/embedding-provider-factory.js +152 -0
  149. package/dist/services/embedding-provider-factory.js.map +1 -0
  150. package/dist/services/embedding-service.d.ts +95 -0
  151. package/dist/services/embedding-service.d.ts.map +1 -0
  152. package/dist/services/embedding-service.js +276 -0
  153. package/dist/services/embedding-service.js.map +1 -0
  154. package/dist/services/error-logging-service.d.ts +134 -0
  155. package/dist/services/error-logging-service.d.ts.map +1 -0
  156. package/dist/services/error-logging-service.js +271 -0
  157. package/dist/services/error-logging-service.js.map +1 -0
  158. package/dist/services/forgetting-policy-service.d.ts +94 -0
  159. package/dist/services/forgetting-policy-service.d.ts.map +1 -0
  160. package/dist/services/forgetting-policy-service.js +233 -0
  161. package/dist/services/forgetting-policy-service.js.map +1 -0
  162. package/dist/services/gemini-embedding-service.d.ts +82 -0
  163. package/dist/services/gemini-embedding-service.d.ts.map +1 -0
  164. package/dist/services/gemini-embedding-service.js +232 -0
  165. package/dist/services/gemini-embedding-service.js.map +1 -0
  166. package/dist/services/lightweight-embedding-service.d.ts +95 -0
  167. package/dist/services/lightweight-embedding-service.d.ts.map +1 -0
  168. package/dist/services/lightweight-embedding-service.js +263 -0
  169. package/dist/services/lightweight-embedding-service.js.map +1 -0
  170. package/dist/services/memory-embedding-service.d.ts +69 -0
  171. package/dist/services/memory-embedding-service.d.ts.map +1 -0
  172. package/dist/services/memory-embedding-service.js +223 -0
  173. package/dist/services/memory-embedding-service.js.map +1 -0
  174. package/dist/services/minilm-embedding-service.d.ts +92 -0
  175. package/dist/services/minilm-embedding-service.d.ts.map +1 -0
  176. package/dist/services/minilm-embedding-service.js +216 -0
  177. package/dist/services/minilm-embedding-service.js.map +1 -0
  178. package/dist/services/performance-alert-service.d.ts +142 -0
  179. package/dist/services/performance-alert-service.d.ts.map +1 -0
  180. package/dist/services/performance-alert-service.js +366 -0
  181. package/dist/services/performance-alert-service.js.map +1 -0
  182. package/dist/services/performance-monitor.d.ts +144 -0
  183. package/dist/services/performance-monitor.d.ts.map +1 -0
  184. package/dist/services/performance-monitor.js +416 -0
  185. package/dist/services/performance-monitor.js.map +1 -0
  186. package/dist/services/performance-monitoring-integration.d.ts +77 -0
  187. package/dist/services/performance-monitoring-integration.d.ts.map +1 -0
  188. package/dist/services/performance-monitoring-integration.js +177 -0
  189. package/dist/services/performance-monitoring-integration.js.map +1 -0
  190. package/dist/services/unified-embedding-service.d.ts +75 -0
  191. package/dist/services/unified-embedding-service.d.ts.map +1 -0
  192. package/dist/services/unified-embedding-service.js +211 -0
  193. package/dist/services/unified-embedding-service.js.map +1 -0
  194. package/dist/test/debug-http-v2.d.ts +5 -0
  195. package/dist/test/debug-http-v2.d.ts.map +1 -0
  196. package/dist/test/debug-http-v2.js +28 -0
  197. package/dist/test/debug-http-v2.js.map +1 -0
  198. package/dist/test/performance-benchmark.d.ts +57 -0
  199. package/dist/test/performance-benchmark.d.ts.map +1 -0
  200. package/dist/test/performance-benchmark.js +427 -0
  201. package/dist/test/performance-benchmark.js.map +1 -0
  202. package/dist/test/test-alerts-direct.d.ts +7 -0
  203. package/dist/test/test-alerts-direct.d.ts.map +1 -0
  204. package/dist/test/test-alerts-direct.js +101 -0
  205. package/dist/test/test-alerts-direct.js.map +1 -0
  206. package/dist/test/test-batch-scheduler.d.ts +2 -0
  207. package/dist/test/test-batch-scheduler.d.ts.map +1 -0
  208. package/dist/test/test-batch-scheduler.js +156 -0
  209. package/dist/test/test-batch-scheduler.js.map +1 -0
  210. package/dist/test/test-client.d.ts +5 -0
  211. package/dist/test/test-client.d.ts.map +1 -0
  212. package/dist/test/test-client.js +86 -0
  213. package/dist/test/test-client.js.map +1 -0
  214. package/dist/test/test-embedding.d.ts +6 -0
  215. package/dist/test/test-embedding.d.ts.map +1 -0
  216. package/dist/test/test-embedding.js +142 -0
  217. package/dist/test/test-embedding.js.map +1 -0
  218. package/dist/test/test-error-logging.d.ts +7 -0
  219. package/dist/test/test-error-logging.d.ts.map +1 -0
  220. package/dist/test/test-error-logging.js +105 -0
  221. package/dist/test/test-error-logging.js.map +1 -0
  222. package/dist/test/test-forgetting.d.ts +6 -0
  223. package/dist/test/test-forgetting.d.ts.map +1 -0
  224. package/dist/test/test-forgetting.js +154 -0
  225. package/dist/test/test-forgetting.js.map +1 -0
  226. package/dist/test/test-gemini-embedding.d.ts +7 -0
  227. package/dist/test/test-gemini-embedding.d.ts.map +1 -0
  228. package/dist/test/test-gemini-embedding.js +134 -0
  229. package/dist/test/test-gemini-embedding.js.map +1 -0
  230. package/dist/test/test-http-server-v2-simple.d.ts +6 -0
  231. package/dist/test/test-http-server-v2-simple.d.ts.map +1 -0
  232. package/dist/test/test-http-server-v2-simple.js +131 -0
  233. package/dist/test/test-http-server-v2-simple.js.map +1 -0
  234. package/dist/test/test-http-server-v2.d.ts +7 -0
  235. package/dist/test/test-http-server-v2.d.ts.map +1 -0
  236. package/dist/test/test-http-server-v2.js +529 -0
  237. package/dist/test/test-http-server-v2.js.map +1 -0
  238. package/dist/test/test-lightweight-embedding.d.ts +6 -0
  239. package/dist/test/test-lightweight-embedding.d.ts.map +1 -0
  240. package/dist/test/test-lightweight-embedding.js +189 -0
  241. package/dist/test/test-lightweight-embedding.js.map +1 -0
  242. package/dist/test/test-m1-completion.d.ts +7 -0
  243. package/dist/test/test-m1-completion.d.ts.map +1 -0
  244. package/dist/test/test-m1-completion.js +124 -0
  245. package/dist/test/test-m1-completion.js.map +1 -0
  246. package/dist/test/test-memory-injection-prompt.d.ts +2 -0
  247. package/dist/test/test-memory-injection-prompt.d.ts.map +1 -0
  248. package/dist/test/test-memory-injection-prompt.js +299 -0
  249. package/dist/test/test-memory-injection-prompt.js.map +1 -0
  250. package/dist/test/test-performance-alerts.d.ts +7 -0
  251. package/dist/test/test-performance-alerts.d.ts.map +1 -0
  252. package/dist/test/test-performance-alerts.js +109 -0
  253. package/dist/test/test-performance-alerts.js.map +1 -0
  254. package/dist/test/test-performance-monitor.d.ts +2 -0
  255. package/dist/test/test-performance-monitor.d.ts.map +1 -0
  256. package/dist/test/test-performance-monitor.js +182 -0
  257. package/dist/test/test-performance-monitor.js.map +1 -0
  258. package/dist/test/test-performance-monitoring.d.ts +6 -0
  259. package/dist/test/test-performance-monitoring.d.ts.map +1 -0
  260. package/dist/test/test-performance-monitoring.js +156 -0
  261. package/dist/test/test-performance-monitoring.js.map +1 -0
  262. package/dist/test/test-search.d.ts +5 -0
  263. package/dist/test/test-search.d.ts.map +1 -0
  264. package/dist/test/test-search.js +141 -0
  265. package/dist/test/test-search.js.map +1 -0
  266. package/dist/test/test-simple-alerts.d.ts +6 -0
  267. package/dist/test/test-simple-alerts.d.ts.map +1 -0
  268. package/dist/test/test-simple-alerts.js +106 -0
  269. package/dist/test/test-simple-alerts.js.map +1 -0
  270. package/dist/test/test-vector-search-engine.d.ts +2 -0
  271. package/dist/test/test-vector-search-engine.d.ts.map +1 -0
  272. package/dist/test/test-vector-search-engine.js +225 -0
  273. package/dist/test/test-vector-search-engine.js.map +1 -0
  274. package/dist/tools/base-tool.d.ts +64 -0
  275. package/dist/tools/base-tool.d.ts.map +1 -0
  276. package/dist/tools/base-tool.js +158 -0
  277. package/dist/tools/base-tool.js.map +1 -0
  278. package/dist/tools/cleanup-memory-tool.d.ts +10 -0
  279. package/dist/tools/cleanup-memory-tool.d.ts.map +1 -0
  280. package/dist/tools/cleanup-memory-tool.js +66 -0
  281. package/dist/tools/cleanup-memory-tool.js.map +1 -0
  282. package/dist/tools/database-optimize-tool.d.ts +10 -0
  283. package/dist/tools/database-optimize-tool.d.ts.map +1 -0
  284. package/dist/tools/database-optimize-tool.js +64 -0
  285. package/dist/tools/database-optimize-tool.js.map +1 -0
  286. package/dist/tools/error-stats.d.ts +93 -0
  287. package/dist/tools/error-stats.d.ts.map +1 -0
  288. package/dist/tools/error-stats.js +115 -0
  289. package/dist/tools/error-stats.js.map +1 -0
  290. package/dist/tools/forget-tool.d.ts +63 -0
  291. package/dist/tools/forget-tool.d.ts.map +1 -0
  292. package/dist/tools/forget-tool.js +340 -0
  293. package/dist/tools/forget-tool.js.map +1 -0
  294. package/dist/tools/forgetting-stats-tool.d.ts +10 -0
  295. package/dist/tools/forgetting-stats-tool.d.ts.map +1 -0
  296. package/dist/tools/forgetting-stats-tool.js +37 -0
  297. package/dist/tools/forgetting-stats-tool.js.map +1 -0
  298. package/dist/tools/index.d.ts +33 -0
  299. package/dist/tools/index.d.ts.map +1 -0
  300. package/dist/tools/index.js +55 -0
  301. package/dist/tools/index.js.map +1 -0
  302. package/dist/tools/memory-injection-prompt.d.ts +31 -0
  303. package/dist/tools/memory-injection-prompt.d.ts.map +1 -0
  304. package/dist/tools/memory-injection-prompt.js +203 -0
  305. package/dist/tools/memory-injection-prompt.js.map +1 -0
  306. package/dist/tools/performance-alerts.d.ts +127 -0
  307. package/dist/tools/performance-alerts.d.ts.map +1 -0
  308. package/dist/tools/performance-alerts.js +208 -0
  309. package/dist/tools/performance-alerts.js.map +1 -0
  310. package/dist/tools/performance-stats-tool.d.ts +10 -0
  311. package/dist/tools/performance-stats-tool.d.ts.map +1 -0
  312. package/dist/tools/performance-stats-tool.js +38 -0
  313. package/dist/tools/performance-stats-tool.js.map +1 -0
  314. package/dist/tools/pin-tool.d.ts +39 -0
  315. package/dist/tools/pin-tool.d.ts.map +1 -0
  316. package/dist/tools/pin-tool.js +211 -0
  317. package/dist/tools/pin-tool.js.map +1 -0
  318. package/dist/tools/recall-tool.d.ts +27 -0
  319. package/dist/tools/recall-tool.d.ts.map +1 -0
  320. package/dist/tools/recall-tool.js +335 -0
  321. package/dist/tools/recall-tool.js.map +1 -0
  322. package/dist/tools/remember-tool.d.ts +10 -0
  323. package/dist/tools/remember-tool.d.ts.map +1 -0
  324. package/dist/tools/remember-tool.js +101 -0
  325. package/dist/tools/remember-tool.js.map +1 -0
  326. package/dist/tools/resolve-error.d.ts +54 -0
  327. package/dist/tools/resolve-error.d.ts.map +1 -0
  328. package/dist/tools/resolve-error.js +63 -0
  329. package/dist/tools/resolve-error.js.map +1 -0
  330. package/dist/tools/tool-registry.d.ts +134 -0
  331. package/dist/tools/tool-registry.d.ts.map +1 -0
  332. package/dist/tools/tool-registry.js +337 -0
  333. package/dist/tools/tool-registry.js.map +1 -0
  334. package/dist/tools/types.d.ts +56 -0
  335. package/dist/tools/types.d.ts.map +1 -0
  336. package/dist/tools/types.js +23 -0
  337. package/dist/tools/types.js.map +1 -0
  338. package/dist/tools/unpin-tool.d.ts +43 -0
  339. package/dist/tools/unpin-tool.d.ts.map +1 -0
  340. package/dist/tools/unpin-tool.js +233 -0
  341. package/dist/tools/unpin-tool.js.map +1 -0
  342. package/dist/types/embedding.types.d.ts +65 -0
  343. package/dist/types/embedding.types.d.ts.map +1 -0
  344. package/dist/types/embedding.types.js +6 -0
  345. package/dist/types/embedding.types.js.map +1 -0
  346. package/dist/types/index.d.ts +103 -0
  347. package/dist/types/index.d.ts.map +1 -0
  348. package/dist/types/index.js +5 -0
  349. package/dist/types/index.js.map +1 -0
  350. package/dist/utils/database.d.ts +62 -0
  351. package/dist/utils/database.d.ts.map +1 -0
  352. package/dist/utils/database.js +399 -0
  353. package/dist/utils/database.js.map +1 -0
  354. package/dist/utils/stopwords.d.ts +18 -0
  355. package/dist/utils/stopwords.d.ts.map +1 -0
  356. package/dist/utils/stopwords.js +117 -0
  357. package/dist/utils/stopwords.js.map +1 -0
  358. package/docker-compose.dev.yml +50 -0
  359. package/docker-compose.prod.yml +77 -0
  360. package/docker-compose.yml +43 -0
  361. package/docs/en/Memento-Goals.md +217 -0
  362. package/docs/en/Memento-M1-DetailSpecs.md +130 -0
  363. package/docs/en/Memento-Milestones.md +135 -0
  364. package/docs/en/Search-Ranking-Memory-Decay-Formulas.md +177 -0
  365. package/docs/en/api-reference.md +658 -0
  366. package/docs/en/architecture.md +1302 -0
  367. package/docs/en/developer-guide.md +1005 -0
  368. package/docs/en/user-manual.md +595 -0
  369. package/docs/ko/Memento-Goals.md +217 -0
  370. package/docs/ko/Memento-M1-DetailSpecs.md +130 -0
  371. package/docs/ko/Memento-Milestones.md +134 -0
  372. package/docs/ko/Search-Ranking-Memory-Decay-Formulas.md +177 -0
  373. package/docs/ko/api-reference.md +658 -0
  374. package/docs/ko/architecture.md +1302 -0
  375. package/docs/ko/developer-guide.md +1006 -0
  376. package/docs/ko/embedding-api-reference.md +122 -0
  377. package/docs/ko/embedding-configuration.md +62 -0
  378. package/docs/ko/embedding-performance-benchmark.md +62 -0
  379. package/docs/ko/embedding-service-guide.md +314 -0
  380. package/docs/ko/user-manual.md +595 -0
  381. package/env.example +49 -0
  382. package/install.sh +191 -0
  383. package/mcp-http-client.js +218 -0
  384. package/mcp.json +0 -0
  385. package/package.json +125 -0
  386. package/packages/mcp-client/docs/API-REFERENCE.md +560 -0
  387. package/packages/mcp-client/docs/BEST-PRACTICES.md +564 -0
  388. package/packages/mcp-client/docs/MIGRATION-GUIDE.md +344 -0
  389. package/packages/mcp-client/docs/PERFORMANCE-GUIDE.md +476 -0
  390. package/packages/mcp-client/docs/TROUBLESHOOTING.md +564 -0
  391. package/packages/mcp-client/package-lock.json +907 -0
  392. package/packages/mcp-client/package.json +58 -0
  393. package/packages/mcp-client/performance-optimizer.js +428 -0
  394. package/packages/mcp-client/test-basic.js +65 -0
  395. package/packages/mcp-client/test-integration.js +366 -0
  396. package/scripts/auto-setup.js +234 -0
  397. package/scripts/backup-daily.bat +28 -0
  398. package/scripts/backup-embeddings.js +108 -0
  399. package/scripts/check-db-integrity.js +93 -0
  400. package/scripts/debug-embeddings.js +184 -0
  401. package/scripts/direct-sql-migration.sql +36 -0
  402. package/scripts/docker-migration.sh +105 -0
  403. package/scripts/fix-migration.js +93 -0
  404. package/scripts/fix-vector-dimensions.js +206 -0
  405. package/scripts/migrate-embedding-data.js +307 -0
  406. package/scripts/regenerate-embeddings.js +144 -0
  407. package/scripts/restore-legacy.ps1 +60 -0
  408. package/scripts/restore-legacy.sh +62 -0
  409. package/scripts/run-migration.js +122 -0
  410. package/scripts/safe-migration.js +150 -0
  411. package/scripts/simple-migrate.js +41 -0
  412. package/scripts/simple-update.js +123 -0
  413. package/scripts/start-container.sh +10 -0
  414. package/src/algorithms/forgetting-algorithm.spec.ts +538 -0
  415. package/src/algorithms/forgetting-algorithm.ts +243 -0
  416. package/src/algorithms/hybrid-search-engine.spec.ts +484 -0
  417. package/src/algorithms/hybrid-search-engine.ts +489 -0
  418. package/src/algorithms/search-engine.spec.ts +429 -0
  419. package/src/algorithms/search-engine.ts +392 -0
  420. package/src/algorithms/search-ranking.spec.ts +293 -0
  421. package/src/algorithms/search-ranking.ts +407 -0
  422. package/src/algorithms/spaced-repetition.spec.ts +510 -0
  423. package/src/algorithms/spaced-repetition.ts +238 -0
  424. package/src/algorithms/vector-search-engine.ts +505 -0
  425. package/src/client/index.spec.ts +427 -0
  426. package/src/client/index.ts +222 -0
  427. package/src/config/index.spec.ts +339 -0
  428. package/src/config/index.ts +106 -0
  429. package/src/database/init.spec.ts +239 -0
  430. package/src/database/init.ts +130 -0
  431. package/src/database/migrate.spec.ts +293 -0
  432. package/src/database/migrate.ts +94 -0
  433. package/src/database/migrations/001_add_embedding_metadata.sql +29 -0
  434. package/src/database/schema.sql +159 -0
  435. package/src/npm-client/context-injector.spec.ts +335 -0
  436. package/src/npm-client/context-injector.ts +412 -0
  437. package/src/npm-client/index.spec.ts +108 -0
  438. package/src/npm-client/index.ts +96 -0
  439. package/src/npm-client/memento-client.spec.ts +549 -0
  440. package/src/npm-client/memento-client.ts +501 -0
  441. package/src/npm-client/memory-manager.spec.ts +374 -0
  442. package/src/npm-client/memory-manager.ts +414 -0
  443. package/src/npm-client/types.spec.ts +427 -0
  444. package/src/npm-client/types.ts +296 -0
  445. package/src/npm-client/utils.spec.ts +355 -0
  446. package/src/npm-client/utils.ts +423 -0
  447. package/src/scripts/copy-assets.js +37 -0
  448. package/src/server/http-server.spec.ts +648 -0
  449. package/src/server/http-server.ts +1030 -0
  450. package/src/server/index-backup.ts +875 -0
  451. package/src/server/index-refactored.ts +237 -0
  452. package/src/server/index.spec.ts +281 -0
  453. package/src/server/index.ts +347 -0
  454. package/src/server/simple-mcp-server.spec.ts +207 -0
  455. package/src/server/simple-mcp-server.ts +173 -0
  456. package/src/services/async-optimizer.spec.ts +569 -0
  457. package/src/services/async-optimizer.ts +484 -0
  458. package/src/services/batch-scheduler.ts +759 -0
  459. package/src/services/cache-service.spec.ts +372 -0
  460. package/src/services/cache-service.ts +434 -0
  461. package/src/services/database-optimizer.spec.ts +344 -0
  462. package/src/services/database-optimizer.ts +450 -0
  463. package/src/services/embedding-provider-factory.ts +173 -0
  464. package/src/services/embedding-service.spec.ts +342 -0
  465. package/src/services/embedding-service.ts +333 -0
  466. package/src/services/error-logging-service.spec.ts +416 -0
  467. package/src/services/error-logging-service.ts +383 -0
  468. package/src/services/forgetting-policy-service.spec.ts +140 -0
  469. package/src/services/forgetting-policy-service.ts +334 -0
  470. package/src/services/gemini-embedding-service.spec.ts +463 -0
  471. package/src/services/gemini-embedding-service.ts +283 -0
  472. package/src/services/lightweight-embedding-service.spec.ts +458 -0
  473. package/src/services/lightweight-embedding-service.ts +324 -0
  474. package/src/services/memory-embedding-service.spec.ts +417 -0
  475. package/src/services/memory-embedding-service.ts +289 -0
  476. package/src/services/minilm-embedding-service.spec.ts +104 -0
  477. package/src/services/minilm-embedding-service.ts +262 -0
  478. package/src/services/performance-alert-service.spec.ts +517 -0
  479. package/src/services/performance-alert-service.ts +477 -0
  480. package/src/services/performance-monitor.spec.ts +401 -0
  481. package/src/services/performance-monitor.ts +532 -0
  482. package/src/services/performance-monitoring-integration.spec.ts +478 -0
  483. package/src/services/performance-monitoring-integration.ts.bak +276 -0
  484. package/src/services/unified-embedding-service.spec.ts +224 -0
  485. package/src/services/unified-embedding-service.ts +255 -0
  486. package/src/test/debug-http-v2.ts +30 -0
  487. package/src/test/embedding-integration-test.spec.ts +295 -0
  488. package/src/test/embedding-integration-test.ts +295 -0
  489. package/src/test/embedding-performance-benchmark.spec.ts +354 -0
  490. package/src/test/embedding-performance-benchmark.ts +312 -0
  491. package/src/test/performance-benchmark.ts +565 -0
  492. package/src/test/test-alerts-direct.ts +136 -0
  493. package/src/test/test-batch-scheduler-simple.spec.ts +122 -0
  494. package/src/test/test-batch-scheduler.spec.ts +453 -0
  495. package/src/test/test-batch-scheduler.ts +182 -0
  496. package/src/test/test-client.ts +97 -0
  497. package/src/test/test-embedding.ts +153 -0
  498. package/src/test/test-error-handling.spec.ts +575 -0
  499. package/src/test/test-error-logging.ts +117 -0
  500. package/src/test/test-forgetting.ts +162 -0
  501. package/src/test/test-gemini-embedding.ts +159 -0
  502. package/src/test/test-http-server-v2-simple.ts +147 -0
  503. package/src/test/test-http-server-v2.ts +586 -0
  504. package/src/test/test-hybrid-search-engine.spec.ts +521 -0
  505. package/src/test/test-integration-fixed.spec.ts +612 -0
  506. package/src/test/test-integration.spec.ts +463 -0
  507. package/src/test/test-lightweight-embedding.ts +208 -0
  508. package/src/test/test-m1-completion.spec.ts +614 -0
  509. package/src/test/test-m1-completion.ts +141 -0
  510. package/src/test/test-m1-integration.spec.ts +514 -0
  511. package/src/test/test-memory-injection-prompt.spec.ts +650 -0
  512. package/src/test/test-memory-injection-prompt.ts +391 -0
  513. package/src/test/test-performance-alerts.ts +125 -0
  514. package/src/test/test-performance-monitor-updates.spec.ts +490 -0
  515. package/src/test/test-performance-monitor.spec.ts +284 -0
  516. package/src/test/test-performance-monitor.ts +228 -0
  517. package/src/test/test-performance-monitoring.ts +171 -0
  518. package/src/test/test-search.ts +151 -0
  519. package/src/test/test-simple-alerts.ts +136 -0
  520. package/src/test/test-vector-search-engine.spec.ts +408 -0
  521. package/src/test/test-vector-search-engine.ts +303 -0
  522. package/src/tools/base-tool.ts +189 -0
  523. package/src/tools/cleanup-memory-tool.ts +77 -0
  524. package/src/tools/database-optimize-tool.ts +79 -0
  525. package/src/tools/error-stats.ts +119 -0
  526. package/src/tools/forget-tool.spec.ts +613 -0
  527. package/src/tools/forget-tool.ts +454 -0
  528. package/src/tools/forgetting-stats-tool.ts +47 -0
  529. package/src/tools/index.ts +71 -0
  530. package/src/tools/memory-injection-prompt.ts +257 -0
  531. package/src/tools/performance-alerts.ts +226 -0
  532. package/src/tools/performance-stats-tool.ts +48 -0
  533. package/src/tools/pin-tool.spec.ts +497 -0
  534. package/src/tools/pin-tool.ts +277 -0
  535. package/src/tools/recall-tool.spec.ts +475 -0
  536. package/src/tools/recall-tool.ts +389 -0
  537. package/src/tools/remember-tool.spec.ts +469 -0
  538. package/src/tools/remember-tool.ts +112 -0
  539. package/src/tools/resolve-error.ts +69 -0
  540. package/src/tools/tool-registry.ts +417 -0
  541. package/src/tools/types.ts +63 -0
  542. package/src/tools/unpin-tool.spec.ts +549 -0
  543. package/src/tools/unpin-tool.ts +306 -0
  544. package/src/types/embedding.types.ts +78 -0
  545. package/src/types/index.spec.ts +420 -0
  546. package/src/types/index.ts +117 -0
  547. package/src/utils/database.spec.ts +77 -0
  548. package/src/utils/database.ts +458 -0
  549. package/src/utils/stopwords.ts +128 -0
  550. package/start-docker-setup.bat +38 -0
  551. package/static/logo.png +0 -0
  552. package/static/memento_logo.svg +2 -0
  553. package/test-docker.js +103 -0
  554. package/tsconfig.json +46 -0
  555. package/vitest.config.ts +23 -0
@@ -0,0 +1,1030 @@
1
+ /**
2
+ * HTTP/WebSocket 기반 MCP μ„œλ²„ v2
3
+ * λͺ¨λ“ˆν™”λœ ꡬ쑰둜 μƒˆλ‘œ κ΅¬ν˜„
4
+ */
5
+
6
+ import express from 'express';
7
+ import { WebSocketServer } from 'ws';
8
+ import cors from 'cors';
9
+ import { createServer } from 'http';
10
+ import { initializeDatabase, closeDatabase } from '../database/init.js';
11
+ import { mementoConfig, validateConfig } from '../config/index.js';
12
+ import { SearchEngine } from '../algorithms/search-engine.js';
13
+ import { HybridSearchEngine } from '../algorithms/hybrid-search-engine.js';
14
+ import { getVectorSearchEngine } from '../algorithms/vector-search-engine.js';
15
+ import { MemoryEmbeddingService } from '../services/memory-embedding-service.js';
16
+ import { getBatchScheduler } from '../services/batch-scheduler.js';
17
+ import { getPerformanceMonitor } from '../services/performance-monitor.js';
18
+ import { getToolRegistry } from '../tools/index.js';
19
+ import type { ToolContext } from '../tools/types.js';
20
+ import Database from 'better-sqlite3';
21
+
22
+ // μ „μ—­ λ³€μˆ˜
23
+ let db: Database.Database | null = null;
24
+ let searchEngine: SearchEngine;
25
+ let hybridSearchEngine: HybridSearchEngine;
26
+ let vectorSearchEngine: ReturnType<typeof getVectorSearchEngine>;
27
+ let embeddingService: MemoryEmbeddingService;
28
+
29
+ type TestDependencies = {
30
+ database: Database.Database;
31
+ searchEngine?: SearchEngine;
32
+ hybridSearchEngine?: HybridSearchEngine;
33
+ embeddingService?: MemoryEmbeddingService;
34
+ };
35
+
36
+ function setTestDependencies({
37
+ database,
38
+ searchEngine: search,
39
+ hybridSearchEngine: hybrid,
40
+ embeddingService: embedding
41
+ }: TestDependencies): void {
42
+ db = database;
43
+ searchEngine = search ?? new SearchEngine();
44
+ hybridSearchEngine = hybrid ?? new HybridSearchEngine();
45
+ embeddingService = embedding ?? new MemoryEmbeddingService();
46
+ }
47
+
48
+ // Express μ•± 생성
49
+ const app = express();
50
+ const server = createServer(app);
51
+
52
+ // 미듀웨어 μ„€μ •
53
+ app.use(cors({
54
+ origin: '*',
55
+ methods: ['GET', 'POST', 'OPTIONS'],
56
+ allowedHeaders: ['Content-Type', 'Authorization', 'Cache-Control']
57
+ }));
58
+ app.use(express.json({ limit: '10mb' }));
59
+ app.use(express.urlencoded({ extended: true }));
60
+
61
+ // κΈ°λ³Έ API μ—”λ“œν¬μΈνŠΈ
62
+ app.get('/health', (req, res) => {
63
+ res.json({
64
+ status: 'healthy',
65
+ server: mementoConfig.serverName,
66
+ version: mementoConfig.serverVersion,
67
+ database: db ? 'connected' : 'disconnected',
68
+ timestamp: new Date().toISOString()
69
+ });
70
+ });
71
+
72
+ app.get('/tools', (req, res) => {
73
+ try {
74
+ const toolRegistry = getToolRegistry();
75
+ const tools = toolRegistry.getAll();
76
+ res.json({
77
+ tools,
78
+ count: tools.length,
79
+ server: mementoConfig.serverName
80
+ });
81
+ } catch (error) {
82
+ console.error('❌ 도ꡬ λͺ©λ‘ 쑰회 μ‹€νŒ¨:', error);
83
+ res.status(500).json({
84
+ error: 'Failed to get tools',
85
+ message: error instanceof Error ? error.message : 'Unknown error'
86
+ });
87
+ }
88
+ });
89
+
90
+ // 도ꡬ μ‹€ν–‰ μ—”λ“œν¬μΈνŠΈ
91
+ app.post('/tools/:name', async (req, res) => {
92
+ const { name } = req.params;
93
+ const params = req.body;
94
+
95
+ try {
96
+ const toolRegistry = getToolRegistry();
97
+
98
+ // 도ꡬ μ»¨ν…μŠ€νŠΈ 생성
99
+ const context: ToolContext = {
100
+ db,
101
+ services: {
102
+ searchEngine,
103
+ hybridSearchEngine,
104
+ embeddingService
105
+ }
106
+ };
107
+
108
+ // 도ꡬ μ‹€ν–‰
109
+ const result = await toolRegistry.execute(name, params, context);
110
+ return res.json({
111
+ result,
112
+ tool: name,
113
+ timestamp: new Date().toISOString()
114
+ });
115
+ } catch (error) {
116
+ console.error(`❌ Tool ${name} μ‹€ν–‰ μ‹€νŒ¨:`, error);
117
+ return res.status(500).json({
118
+ error: 'Tool execution failed',
119
+ tool: name,
120
+ message: error instanceof Error ? error.message : 'Unknown error'
121
+ });
122
+ }
123
+ });
124
+
125
+ // MCP SSE μ—”λ“œν¬μΈνŠΈ - MCP SDK ν˜Έν™˜ κ΅¬ν˜„
126
+ // Store transports by session ID
127
+ const transports: { [sessionId: string]: any } = {};
128
+
129
+ // SSE endpoint for establishing the stream
130
+ app.get('/mcp', async (req, res) => {
131
+ console.log('πŸ”— MCP SSE ν΄λΌμ΄μ–ΈνŠΈ μ—°κ²° μš”μ²­');
132
+
133
+ try {
134
+ // SSE 헀더 μ„€μ •
135
+ res.writeHead(200, {
136
+ 'Content-Type': 'text/event-stream',
137
+ 'Cache-Control': 'no-cache, no-transform',
138
+ 'Connection': 'keep-alive',
139
+ 'Access-Control-Allow-Origin': '*',
140
+ 'Access-Control-Allow-Headers': 'Cache-Control, Content-Type, Authorization',
141
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
142
+ 'X-Accel-Buffering': 'no' // nginx 버퍼링 λΉ„ν™œμ„±ν™”
143
+ });
144
+
145
+ // Generate session ID
146
+ const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
147
+
148
+ // Send the endpoint event with session ID
149
+ const endpointUrl = `/messages?sessionId=${sessionId}`;
150
+ res.write(`event: endpoint\ndata: ${endpointUrl}\n\n`);
151
+
152
+ // MCP μ„œλ²„ μ€€λΉ„ μ™„λ£Œ μ•Œλ¦Ό (ν΄λΌμ΄μ–ΈνŠΈκ°€ initializeλ₯Ό 보내야 함)
153
+ res.write(`data: {"type": "ready"}\n\n`);
154
+
155
+ // Keep-alive ping 전솑
156
+ const keepAliveInterval = setInterval(() => {
157
+ if (res.writableEnded) {
158
+ clearInterval(keepAliveInterval);
159
+ return;
160
+ }
161
+ try {
162
+ res.write(`data: {"type": "ping"}\n\n`);
163
+ } catch (error) {
164
+ clearInterval(keepAliveInterval);
165
+ }
166
+ }, 30000); // 30μ΄ˆλ§ˆλ‹€ ping
167
+
168
+ // Store the transport info
169
+ transports[sessionId] = {
170
+ res: res,
171
+ sessionId: sessionId,
172
+ keepAliveInterval: keepAliveInterval
173
+ };
174
+
175
+ // μ—°κ²° μ’…λ£Œ 처리
176
+ req.on('close', () => {
177
+ console.log(`πŸ”Œ MCP SSE ν΄λΌμ΄μ–ΈνŠΈ μ—°κ²° 정상 μ’…λ£Œλ¨ (session: ${sessionId})`);
178
+ clearInterval(keepAliveInterval);
179
+ delete transports[sessionId];
180
+ });
181
+
182
+ req.on('error', (error) => {
183
+ // ECONNRESET은 정상적인 μ—°κ²° μ’…λ£Œμ΄λ―€λ‘œ μ—λŸ¬λ‘œ μ²˜λ¦¬ν•˜μ§€ μ•ŠμŒ
184
+ if ((error as any).code === 'ECONNRESET') {
185
+ console.log(`πŸ”Œ MCP SSE ν΄λΌμ΄μ–ΈνŠΈ μ—°κ²° 정상 μ’…λ£Œλ¨ (session: ${sessionId})`);
186
+ } else {
187
+ console.error(`❌ MCP SSE μ—°κ²° μ—λŸ¬ (session: ${sessionId}):`, error);
188
+ }
189
+ clearInterval(keepAliveInterval);
190
+ delete transports[sessionId];
191
+ });
192
+
193
+ console.log(`βœ… MCP SSE 슀트림 μ„€μ • μ™„λ£Œ (session: ${sessionId})`);
194
+ return;
195
+
196
+ } catch (error) {
197
+ console.error('❌ SSE 슀트림 μ„€μ • μ‹€νŒ¨:', error);
198
+ if (!res.headersSent) {
199
+ res.status(500).send('Error establishing SSE stream');
200
+ }
201
+ return;
202
+ }
203
+ });
204
+
205
+ // Messages endpoint for receiving client JSON-RPC requests
206
+ app.post('/messages', express.json(), async (req, res) => {
207
+ console.log('πŸ“¨ MCP λ©”μ‹œμ§€ μˆ˜μ‹ :', req.body.method);
208
+
209
+ // Extract session ID from URL query parameter
210
+ const sessionId = req.query.sessionId as string;
211
+ if (!sessionId) {
212
+ console.error('❌ No session ID provided in request URL');
213
+ res.status(400).send('Missing sessionId parameter');
214
+ return;
215
+ }
216
+
217
+ const transport = transports[sessionId];
218
+ if (!transport) {
219
+ console.error(`❌ No active transport found for session ID: ${sessionId}`);
220
+ res.status(404).send('Session not found');
221
+ return;
222
+ }
223
+
224
+ let message = req.body;
225
+ let result;
226
+
227
+ console.log(`πŸ” MCP λ©”μ‹œμ§€ 처리 쀑: ${message.method}`, JSON.stringify(message, null, 2));
228
+
229
+ try {
230
+
231
+ if (message.method === 'initialize') {
232
+ console.log('πŸš€ MCP initialize μš”μ²­ 처리 쀑...');
233
+ result = {
234
+ jsonrpc: '2.0',
235
+ id: message.id,
236
+ result: {
237
+ protocolVersion: '2024-11-05',
238
+ capabilities: {
239
+ tools: {}
240
+ },
241
+ serverInfo: {
242
+ name: 'memento-memory',
243
+ version: '0.1.0'
244
+ }
245
+ }
246
+ };
247
+ console.log('βœ… MCP initialize 응닡 생성 μ™„λ£Œ:', JSON.stringify(result, null, 2));
248
+ } else if (message.method === 'notifications/initialized') {
249
+ console.log('πŸ”” MCP initialized μ•Œλ¦Ό μˆ˜μ‹ ');
250
+ result = {
251
+ jsonrpc: '2.0',
252
+ id: message.id,
253
+ result: {}
254
+ };
255
+ } else if (message.method === 'tools/list') {
256
+ console.log('πŸ“‹ MCP tools/list μš”μ²­ 처리 쀑...');
257
+
258
+ try {
259
+ const toolRegistry = getToolRegistry();
260
+ const tools = toolRegistry.getAll();
261
+
262
+ console.log('πŸ” 도ꡬ λͺ©λ‘ μ‚¬μš©, 길이:', tools.length);
263
+
264
+ result = {
265
+ jsonrpc: '2.0',
266
+ id: message.id,
267
+ result: { tools }
268
+ };
269
+
270
+ console.log('βœ… MCP tools/list 응닡 생성 μ™„λ£Œ, tools 개수:', tools.length);
271
+ console.log('πŸ” 응닡 크기:', JSON.stringify(result).length, 'bytes');
272
+
273
+ // SSE 응닡 μ¦‰μ‹œ 전솑
274
+ console.log('πŸ“€ SSE 응닡 μ¦‰μ‹œ 전솑 쀑...');
275
+ if (transport && transport.res && !transport.res.writableEnded) {
276
+ const sseData = `data: ${JSON.stringify(result)}\n\n`;
277
+ transport.res.write(sseData);
278
+ console.log('βœ… SSE 응닡 μ¦‰μ‹œ 전솑 μ™„λ£Œ, 크기:', sseData.length, 'bytes');
279
+ } else {
280
+ console.error('❌ SSE transportκ°€ μœ νš¨ν•˜μ§€ μ•ŠμŒ');
281
+ }
282
+
283
+ // HTTP 응닡 전솑
284
+ res.json({ status: 'ok' });
285
+ return;
286
+
287
+ } catch (toolsError) {
288
+ console.error('❌ tools/list 처리 쀑 였λ₯˜:', toolsError);
289
+ const errorResult = {
290
+ jsonrpc: '2.0',
291
+ id: message.id,
292
+ error: {
293
+ code: -32603,
294
+ message: 'Internal error',
295
+ data: toolsError instanceof Error ? toolsError.message : String(toolsError)
296
+ }
297
+ };
298
+
299
+ if (transport && transport.res && !transport.res.writableEnded) {
300
+ transport.res.write(`data: ${JSON.stringify(errorResult)}\n\n`);
301
+ }
302
+ res.json({ status: 'error' });
303
+ return;
304
+ }
305
+ } else if (message.method === 'tools/call') {
306
+ const { name, arguments: args } = message.params;
307
+
308
+ const toolRegistry = getToolRegistry();
309
+
310
+ // 도ꡬ μ»¨ν…μŠ€νŠΈ 생성
311
+ const context: ToolContext = {
312
+ db,
313
+ services: {
314
+ searchEngine,
315
+ hybridSearchEngine,
316
+ embeddingService
317
+ }
318
+ };
319
+
320
+ // 도ꡬ μ‹€ν–‰
321
+ const toolResult = await toolRegistry.execute(name, args, context);
322
+
323
+ result = {
324
+ jsonrpc: '2.0',
325
+ id: message.id,
326
+ result: { content: [{ type: 'text', text: JSON.stringify(toolResult) }] }
327
+ };
328
+ } else if (message.method === 'prompts/list') {
329
+ console.log('πŸ“‹ MCP prompts/list μš”μ²­ 처리 쀑...');
330
+
331
+ const prompts = [
332
+ {
333
+ name: 'memory_injection',
334
+ description: 'κ΄€λ ¨ 기얡을 μš”μ•½ν•˜μ—¬ ν”„λ‘¬ν”„νŠΈμ— μ£Όμž…',
335
+ arguments: [
336
+ {
337
+ name: 'query',
338
+ description: '검색할 쿼리',
339
+ required: true
340
+ },
341
+ {
342
+ name: 'token_budget',
343
+ description: '토큰 μ˜ˆμ‚° (κΈ°λ³Έκ°’: 1000)',
344
+ required: false
345
+ },
346
+ {
347
+ name: 'max_memories',
348
+ description: 'μ΅œλŒ€ κΈ°μ–΅ 개수 (κΈ°λ³Έκ°’: 5)',
349
+ required: false
350
+ }
351
+ ]
352
+ }
353
+ ];
354
+
355
+ result = {
356
+ jsonrpc: '2.0',
357
+ id: message.id,
358
+ result: { prompts }
359
+ };
360
+
361
+ console.log('βœ… MCP prompts/list 응닡 생성 μ™„λ£Œ');
362
+ } else if (message.method === 'prompts/get') {
363
+ const { name } = message.params;
364
+
365
+ if (name === 'memory_injection') {
366
+ result = {
367
+ jsonrpc: '2.0',
368
+ id: message.id,
369
+ result: {
370
+ description: 'κ΄€λ ¨ 기얡을 μš”μ•½ν•˜μ—¬ ν”„λ‘¬ν”„νŠΈμ— μ£Όμž…',
371
+ arguments: [
372
+ {
373
+ name: 'query',
374
+ description: '검색할 쿼리',
375
+ required: true
376
+ },
377
+ {
378
+ name: 'token_budget',
379
+ description: '토큰 μ˜ˆμ‚° (κΈ°λ³Έκ°’: 1000)',
380
+ required: false
381
+ },
382
+ {
383
+ name: 'max_memories',
384
+ description: 'μ΅œλŒ€ κΈ°μ–΅ 개수 (κΈ°λ³Έκ°’: 5)',
385
+ required: false
386
+ }
387
+ ]
388
+ }
389
+ };
390
+ } else {
391
+ result = {
392
+ jsonrpc: '2.0',
393
+ id: message.id,
394
+ error: {
395
+ code: -32601,
396
+ message: 'Prompt not found'
397
+ }
398
+ };
399
+ }
400
+ } else if (message.method === 'prompts/call') {
401
+ const { name, arguments: args } = message.params;
402
+
403
+ if (name === 'memory_injection') {
404
+ try {
405
+ // MemoryInjectionPrompt 도ꡬ μ‚¬μš©
406
+ const toolRegistry = getToolRegistry();
407
+ const context: ToolContext = {
408
+ db,
409
+ services: {
410
+ searchEngine,
411
+ hybridSearchEngine,
412
+ embeddingService
413
+ }
414
+ };
415
+
416
+ const promptResult = await toolRegistry.execute('memory_injection', args, context);
417
+
418
+ result = {
419
+ jsonrpc: '2.0',
420
+ id: message.id,
421
+ result: promptResult
422
+ };
423
+ } catch (error) {
424
+ result = {
425
+ jsonrpc: '2.0',
426
+ id: message.id,
427
+ error: {
428
+ code: -32603,
429
+ message: 'Prompt execution failed',
430
+ data: error instanceof Error ? error.message : 'Unknown error'
431
+ }
432
+ };
433
+ }
434
+ } else {
435
+ result = {
436
+ jsonrpc: '2.0',
437
+ id: message.id,
438
+ error: {
439
+ code: -32601,
440
+ message: 'Prompt not found'
441
+ }
442
+ };
443
+ }
444
+ } else {
445
+ result = {
446
+ jsonrpc: '2.0',
447
+ id: message.id,
448
+ error: {
449
+ code: -32601,
450
+ message: 'Method not found'
451
+ }
452
+ };
453
+ }
454
+
455
+ // Send response via SSE
456
+ console.log('πŸ“€ SSE 응닡 전솑 쀑:', JSON.stringify(result).substring(0, 200) + '...');
457
+ try {
458
+ // transport 객체 μœ νš¨μ„± 확인
459
+ if (!transport || !transport.res || transport.res.writableEnded) {
460
+ console.error('❌ SSE transportκ°€ μœ νš¨ν•˜μ§€ μ•ŠμŒ');
461
+ res.status(500).json({ error: 'SSE transport invalid' });
462
+ return;
463
+ }
464
+
465
+ // SSE 응닡 전솑
466
+ const sseData = `data: ${JSON.stringify(result)}\n\n`;
467
+ transport.res.write(sseData);
468
+ console.log('βœ… SSE 응닡 전솑 μ™„λ£Œ, 크기:', sseData.length, 'bytes');
469
+ } catch (sseError) {
470
+ console.error('❌ SSE 응닡 전솑 μ‹€νŒ¨:', sseError);
471
+ // SSE 전솑 μ‹€νŒ¨ μ‹œμ—λ„ HTTP 응닡은 정상 처리
472
+ }
473
+
474
+ // Send HTTP response
475
+ res.json({ status: 'ok' });
476
+
477
+ } catch (error) {
478
+ console.error('❌ MCP λ©”μ‹œμ§€ 처리 μ‹€νŒ¨:', error);
479
+ const errorResponse = {
480
+ jsonrpc: '2.0',
481
+ id: message?.id || null,
482
+ error: {
483
+ code: -32603,
484
+ message: 'Internal error',
485
+ data: error instanceof Error ? error.message : 'Unknown error'
486
+ }
487
+ };
488
+
489
+ // Send error via SSE
490
+ try {
491
+ if (transport && transport.res && !transport.res.writableEnded) {
492
+ const errorSseData = `data: ${JSON.stringify(errorResponse)}\n\n`;
493
+ transport.res.write(errorSseData);
494
+ console.log('βœ… SSE μ—λŸ¬ 응닡 전솑 μ™„λ£Œ');
495
+ } else {
496
+ console.error('❌ SSE transportκ°€ μœ νš¨ν•˜μ§€ μ•Šμ•„ μ—λŸ¬ 응닡 전솑 μ‹€νŒ¨');
497
+ }
498
+ } catch (errorSseError) {
499
+ console.error('❌ SSE μ—λŸ¬ 응닡 전솑 μ‹€νŒ¨:', errorSseError);
500
+ }
501
+
502
+ // Send HTTP response
503
+ res.json({ status: 'error' });
504
+ }
505
+ });
506
+
507
+ // κ΄€λ¦¬μž API μ—”λ“œν¬μΈνŠΈλ“€
508
+ app.post('/admin/memory/cleanup', async (req, res) => {
509
+ try {
510
+ // λ©”λͺ¨λ¦¬ 정리 둜직 (κΈ°μ‘΄ CleanupMemoryTool 둜직)
511
+ if (!db) {
512
+ return res.status(500).json({ error: 'λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ—°κ²°λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€' });
513
+ }
514
+
515
+ // κ°„λ‹¨ν•œ λ©”λͺ¨λ¦¬ 정리 κ΅¬ν˜„
516
+ const result = await db.prepare(`
517
+ DELETE FROM memory_item
518
+ WHERE pinned = FALSE
519
+ AND type = 'working'
520
+ AND created_at < datetime('now', '-2 days')
521
+ `).run();
522
+
523
+ return res.json({
524
+ message: 'λ©”λͺ¨λ¦¬ 정리 μ™„λ£Œ',
525
+ deleted_count: result.changes,
526
+ timestamp: new Date().toISOString()
527
+ });
528
+ } catch (error) {
529
+ console.error('❌ λ©”λͺ¨λ¦¬ 정리 μ‹€νŒ¨:', error);
530
+ return res.status(500).json({
531
+ error: 'λ©”λͺ¨λ¦¬ 정리 μ‹€νŒ¨',
532
+ message: error instanceof Error ? error.message : 'Unknown error'
533
+ });
534
+ }
535
+ });
536
+
537
+ app.get('/admin/stats/forgetting', async (req, res) => {
538
+ try {
539
+ // 망각 톡계 둜직 (κΈ°μ‘΄ ForgettingStatsTool 둜직)
540
+ if (!db) {
541
+ return res.status(500).json({ error: 'λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ—°κ²°λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€' });
542
+ }
543
+
544
+ const stats = await db.prepare(`
545
+ SELECT
546
+ type,
547
+ COUNT(*) as total_count,
548
+ COUNT(CASE WHEN pinned = TRUE THEN 1 END) as pinned_count,
549
+ COUNT(CASE WHEN created_at < datetime('now', '-30 days') THEN 1 END) as old_count
550
+ FROM memory_item
551
+ GROUP BY type
552
+ `).all();
553
+
554
+ return res.json({
555
+ message: '망각 톡계 쑰회 μ™„λ£Œ',
556
+ stats,
557
+ timestamp: new Date().toISOString()
558
+ });
559
+ } catch (error) {
560
+ console.error('❌ 망각 톡계 쑰회 μ‹€νŒ¨:', error);
561
+ return res.status(500).json({
562
+ error: '망각 톡계 쑰회 μ‹€νŒ¨',
563
+ message: error instanceof Error ? error.message : 'Unknown error'
564
+ });
565
+ }
566
+ });
567
+
568
+ app.get('/admin/stats/performance', async (req, res) => {
569
+ try {
570
+ // μ„±λŠ₯ 톡계 둜직 (κΈ°μ‘΄ PerformanceStatsTool 둜직)
571
+ if (!db) {
572
+ return res.status(500).json({ error: 'λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ—°κ²°λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€' });
573
+ }
574
+
575
+ const stats = await db.prepare(`
576
+ SELECT
577
+ COUNT(*) as total_memories,
578
+ COUNT(CASE WHEN type = 'working' THEN 1 END) as working_memories,
579
+ COUNT(CASE WHEN type = 'episodic' THEN 1 END) as episodic_memories,
580
+ COUNT(CASE WHEN type = 'semantic' THEN 1 END) as semantic_memories,
581
+ COUNT(CASE WHEN type = 'procedural' THEN 1 END) as procedural_memories,
582
+ COUNT(CASE WHEN pinned = TRUE THEN 1 END) as pinned_memories
583
+ FROM memory_item
584
+ `).get();
585
+
586
+ return res.json({
587
+ message: 'μ„±λŠ₯ 톡계 쑰회 μ™„λ£Œ',
588
+ stats,
589
+ timestamp: new Date().toISOString()
590
+ });
591
+ } catch (error) {
592
+ console.error('❌ μ„±λŠ₯ 톡계 쑰회 μ‹€νŒ¨:', error);
593
+ return res.status(500).json({
594
+ error: 'μ„±λŠ₯ 톡계 쑰회 μ‹€νŒ¨',
595
+ message: error instanceof Error ? error.message : 'Unknown error'
596
+ });
597
+ }
598
+ });
599
+
600
+ app.post('/admin/database/optimize', async (req, res) => {
601
+ try {
602
+ // λ°μ΄ν„°λ² μ΄μŠ€ μ΅œμ ν™” 둜직 (κΈ°μ‘΄ DatabaseOptimizeTool 둜직)
603
+ if (!db) {
604
+ return res.status(500).json({ error: 'λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ—°κ²°λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€' });
605
+ }
606
+
607
+ // VACUUM μ‹€ν–‰
608
+ await db.prepare('VACUUM').run();
609
+
610
+ // ANALYZE μ‹€ν–‰
611
+ await db.prepare('ANALYZE').run();
612
+
613
+ return res.json({
614
+ message: 'λ°μ΄ν„°λ² μ΄μŠ€ μ΅œμ ν™” μ™„λ£Œ',
615
+ timestamp: new Date().toISOString()
616
+ });
617
+ } catch (error) {
618
+ console.error('❌ λ°μ΄ν„°λ² μ΄μŠ€ μ΅œμ ν™” μ‹€νŒ¨:', error);
619
+ return res.status(500).json({
620
+ error: 'λ°μ΄ν„°λ² μ΄μŠ€ μ΅œμ ν™” μ‹€νŒ¨',
621
+ message: error instanceof Error ? error.message : 'Unknown error'
622
+ });
623
+ }
624
+ });
625
+
626
+ app.get('/admin/stats/errors', async (req, res) => {
627
+ try {
628
+ // μ—λŸ¬ 톡계 둜직 (κΈ°μ‘΄ errorStatsTool 둜직)
629
+ res.json({
630
+ message: 'μ—λŸ¬ 톡계 쑰회 μ™„λ£Œ',
631
+ stats: {
632
+ total_errors: 0,
633
+ recent_errors: [],
634
+ error_types: {}
635
+ },
636
+ timestamp: new Date().toISOString()
637
+ });
638
+ } catch (error) {
639
+ console.error('❌ μ—λŸ¬ 톡계 쑰회 μ‹€νŒ¨:', error);
640
+ res.status(500).json({
641
+ error: 'μ—λŸ¬ 톡계 쑰회 μ‹€νŒ¨',
642
+ message: error instanceof Error ? error.message : 'Unknown error'
643
+ });
644
+ }
645
+ });
646
+
647
+ app.post('/admin/errors/resolve', async (req, res) => {
648
+ try {
649
+ const { errorId, resolvedBy, reason } = req.body;
650
+ // μ—λŸ¬ ν•΄κ²° 둜직 (κΈ°μ‘΄ resolveErrorTool 둜직)
651
+ res.json({
652
+ message: 'μ—λŸ¬ ν•΄κ²° μ™„λ£Œ',
653
+ errorId,
654
+ resolvedBy,
655
+ reason,
656
+ timestamp: new Date().toISOString()
657
+ });
658
+ } catch (error) {
659
+ console.error('❌ μ—λŸ¬ ν•΄κ²° μ‹€νŒ¨:', error);
660
+ res.status(500).json({
661
+ error: 'μ—λŸ¬ ν•΄κ²° μ‹€νŒ¨',
662
+ message: error instanceof Error ? error.message : 'Unknown error'
663
+ });
664
+ }
665
+ });
666
+
667
+ app.get('/admin/alerts/performance', async (req, res) => {
668
+ try {
669
+ // μ„±λŠ₯ μ•Œλ¦Ό 둜직 (κΈ°μ‘΄ performanceAlertsTool 둜직)
670
+ res.json({
671
+ message: 'μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ™„λ£Œ',
672
+ alerts: [],
673
+ timestamp: new Date().toISOString()
674
+ });
675
+ } catch (error) {
676
+ console.error('❌ μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ‹€νŒ¨:', error);
677
+ res.status(500).json({
678
+ error: 'μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ‹€νŒ¨',
679
+ message: error instanceof Error ? error.message : 'Unknown error'
680
+ });
681
+ }
682
+ });
683
+
684
+ // 배치 μŠ€μΌ€μ€„λŸ¬ 관리 API
685
+ app.get('/admin/batch/status', async (req, res) => {
686
+ try {
687
+ const batchScheduler = getBatchScheduler();
688
+ const status = batchScheduler.getStatus();
689
+
690
+ res.json({
691
+ message: '배치 μŠ€μΌ€μ€„λŸ¬ μƒνƒœ 쑰회 μ™„λ£Œ',
692
+ status,
693
+ timestamp: new Date().toISOString()
694
+ });
695
+ } catch (error) {
696
+ console.error('❌ 배치 μŠ€μΌ€μ€„λŸ¬ μƒνƒœ 쑰회 μ‹€νŒ¨:', error);
697
+ res.status(500).json({
698
+ error: '배치 μŠ€μΌ€μ€„λŸ¬ μƒνƒœ 쑰회 μ‹€νŒ¨',
699
+ message: error instanceof Error ? error.message : 'Unknown error'
700
+ });
701
+ }
702
+ });
703
+
704
+ app.post('/admin/batch/run', async (req, res) => {
705
+ try {
706
+ const { jobType } = req.body;
707
+
708
+ if (!jobType || !['cleanup', 'monitoring'].includes(jobType)) {
709
+ return res.status(400).json({
710
+ error: 'Invalid job type. Must be "cleanup" or "monitoring"'
711
+ });
712
+ }
713
+
714
+ const batchScheduler = getBatchScheduler();
715
+ const result = await batchScheduler.runJob(jobType);
716
+
717
+ return res.json({
718
+ message: `배치 μž‘μ—… ${jobType} μ‹€ν–‰ μ™„λ£Œ`,
719
+ result,
720
+ timestamp: new Date().toISOString()
721
+ });
722
+ } catch (error) {
723
+ console.error('❌ 배치 μž‘μ—… μ‹€ν–‰ μ‹€νŒ¨:', error);
724
+ return res.status(500).json({
725
+ error: '배치 μž‘μ—… μ‹€ν–‰ μ‹€νŒ¨',
726
+ message: error instanceof Error ? error.message : 'Unknown error'
727
+ });
728
+ }
729
+ });
730
+
731
+ // μ„±λŠ₯ λͺ¨λ‹ˆν„°λ§ API
732
+ app.get('/admin/performance/metrics', async (req, res) => {
733
+ try {
734
+ const monitor = getPerformanceMonitor();
735
+ const metrics = await monitor.collectMetrics();
736
+
737
+ res.json({
738
+ message: 'μ„±λŠ₯ μ§€ν‘œ μˆ˜μ§‘ μ™„λ£Œ',
739
+ metrics,
740
+ timestamp: new Date().toISOString()
741
+ });
742
+ } catch (error) {
743
+ console.error('❌ μ„±λŠ₯ μ§€ν‘œ μˆ˜μ§‘ μ‹€νŒ¨:', error);
744
+ res.status(500).json({
745
+ error: 'μ„±λŠ₯ μ§€ν‘œ μˆ˜μ§‘ μ‹€νŒ¨',
746
+ message: error instanceof Error ? error.message : 'Unknown error'
747
+ });
748
+ }
749
+ });
750
+
751
+ app.get('/admin/performance/alerts', async (req, res) => {
752
+ try {
753
+ const monitor = getPerformanceMonitor();
754
+ const alerts = monitor.getActiveAlerts();
755
+
756
+ res.json({
757
+ message: 'μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ™„λ£Œ',
758
+ alerts,
759
+ count: alerts.length,
760
+ timestamp: new Date().toISOString()
761
+ });
762
+ } catch (error) {
763
+ console.error('❌ μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ‹€νŒ¨:', error);
764
+ res.status(500).json({
765
+ error: 'μ„±λŠ₯ μ•Œλ¦Ό 쑰회 μ‹€νŒ¨',
766
+ message: error instanceof Error ? error.message : 'Unknown error'
767
+ });
768
+ }
769
+ });
770
+
771
+ app.get('/admin/performance/summary', async (req, res) => {
772
+ try {
773
+ const monitor = getPerformanceMonitor();
774
+ const summary = monitor.getPerformanceSummary();
775
+
776
+ res.json({
777
+ message: 'μ„±λŠ₯ μš”μ•½ 쑰회 μ™„λ£Œ',
778
+ summary,
779
+ timestamp: new Date().toISOString()
780
+ });
781
+ } catch (error) {
782
+ console.error('❌ μ„±λŠ₯ μš”μ•½ 쑰회 μ‹€νŒ¨:', error);
783
+ res.status(500).json({
784
+ error: 'μ„±λŠ₯ μš”μ•½ 쑰회 μ‹€νŒ¨',
785
+ message: error instanceof Error ? error.message : 'Unknown error'
786
+ });
787
+ }
788
+ });
789
+
790
+ app.post('/admin/performance/alerts/:alertId/resolve', async (req, res) => {
791
+ try {
792
+ const { alertId } = req.params;
793
+ const monitor = getPerformanceMonitor();
794
+ const resolved = monitor.resolveAlert(alertId);
795
+
796
+ if (resolved) {
797
+ res.json({
798
+ message: 'μ•Œλ¦Ό ν•΄κ²° μ™„λ£Œ',
799
+ alertId,
800
+ timestamp: new Date().toISOString()
801
+ });
802
+ } else {
803
+ res.status(404).json({
804
+ error: 'μ•Œλ¦Όμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€',
805
+ alertId
806
+ });
807
+ }
808
+ } catch (error) {
809
+ console.error('❌ μ•Œλ¦Ό ν•΄κ²° μ‹€νŒ¨:', error);
810
+ res.status(500).json({
811
+ error: 'μ•Œλ¦Ό ν•΄κ²° μ‹€νŒ¨',
812
+ message: error instanceof Error ? error.message : 'Unknown error'
813
+ });
814
+ }
815
+ });
816
+
817
+ // μ„œλ²„ μ΄ˆκΈ°ν™”
818
+ async function initializeServer() {
819
+ try {
820
+ console.log('πŸš€ HTTP/WebSocket MCP μ„œλ²„ v2 μ‹œμž‘ 쀑...');
821
+
822
+ // μ„€μ • 검증
823
+ validateConfig();
824
+
825
+ // λ°μ΄ν„°λ² μ΄μŠ€ μ΄ˆκΈ°ν™”
826
+ db = await initializeDatabase();
827
+
828
+ // 검색 μ—”μ§„ μ΄ˆκΈ°ν™”
829
+ searchEngine = new SearchEngine();
830
+ hybridSearchEngine = new HybridSearchEngine();
831
+ vectorSearchEngine = getVectorSearchEngine();
832
+ vectorSearchEngine.initialize(db);
833
+ embeddingService = new MemoryEmbeddingService();
834
+
835
+ // 배치 μŠ€μΌ€μ€„λŸ¬ μ‹œμž‘
836
+ const batchScheduler = getBatchScheduler();
837
+ await batchScheduler.start(db);
838
+ console.log('⏰ 배치 μŠ€μΌ€μ€„λŸ¬ μ‹œμž‘λ¨');
839
+
840
+ // μž„λ² λ”© ν”„λ‘œλ°”μ΄λ” 정보 ν‘œμ‹œ
841
+ console.log(`πŸ”§ μž„λ² λ”© ν”„λ‘œλ°”μ΄λ”: ${mementoConfig.embeddingProvider.toUpperCase()}`);
842
+ if (mementoConfig.embeddingProvider === 'openai' && mementoConfig.openaiApiKey) {
843
+ console.log(` πŸ“ λͺ¨λΈ: ${mementoConfig.openaiModel} (${mementoConfig.embeddingDimensions}차원)`);
844
+ } else if (mementoConfig.embeddingProvider === 'gemini' && mementoConfig.geminiApiKey) {
845
+ console.log(` πŸ“ λͺ¨λΈ: ${mementoConfig.geminiModel} (${mementoConfig.embeddingDimensions}차원)`);
846
+ } else if (mementoConfig.embeddingProvider === 'lightweight') {
847
+ console.log(` πŸ“ λͺ¨λΈ: lightweight-hybrid (512차원)`);
848
+ }
849
+
850
+ console.log('βœ… μ„œλ²„ μ΄ˆκΈ°ν™” μ™„λ£Œ');
851
+ console.log(`πŸ“Š μ„œλ²„: ${mementoConfig.serverName} v${mementoConfig.serverVersion}`);
852
+ console.log(`πŸ—„οΈ λ°μ΄ν„°λ² μ΄μŠ€: ${mementoConfig.dbPath}`);
853
+
854
+ } catch (error) {
855
+ console.error('❌ μ„œλ²„ μ΄ˆκΈ°ν™” μ‹€νŒ¨:', error);
856
+ process.exit(1);
857
+ }
858
+ }
859
+
860
+ // 정리 ν•¨μˆ˜
861
+ let isCleaningUp = false;
862
+ async function cleanup() {
863
+ if (isCleaningUp) {
864
+ return;
865
+ }
866
+
867
+ isCleaningUp = true;
868
+
869
+ try {
870
+ // 배치 μŠ€μΌ€μ€„λŸ¬ 쀑지
871
+ const batchScheduler = getBatchScheduler();
872
+ batchScheduler.stop();
873
+ console.log('⏰ 배치 μŠ€μΌ€μ€„λŸ¬ 쀑지됨');
874
+
875
+ if (db) {
876
+ closeDatabase(db);
877
+ db = null;
878
+ }
879
+ console.log('πŸ‘‹ HTTP/WebSocket MCP μ„œλ²„ v2 μ’…λ£Œ');
880
+ } catch (error) {
881
+ console.error('❌ 정리 쀑 였λ₯˜:', error);
882
+ }
883
+ }
884
+
885
+ // ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ μ‹œ 정리
886
+ let cleanupRegistered = false;
887
+ function registerCleanupHandlers() {
888
+ if (cleanupRegistered) {
889
+ return;
890
+ }
891
+
892
+ cleanupRegistered = true;
893
+
894
+ process.on('SIGINT', async () => {
895
+ await cleanup();
896
+ process.exit(0);
897
+ });
898
+
899
+ process.on('SIGTERM', async () => {
900
+ await cleanup();
901
+ process.exit(0);
902
+ });
903
+
904
+ process.on('uncaughtException', async (error) => {
905
+ console.error('❌ μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜:', error);
906
+ await cleanup();
907
+ process.exit(1);
908
+ });
909
+ }
910
+
911
+ // WebSocket μ„œλ²„ μ„€μ •
912
+ const wss = new WebSocketServer({ server });
913
+
914
+ wss.on('connection', (ws) => {
915
+ console.log('πŸ”— WebSocket ν΄λΌμ΄μ–ΈνŠΈ 연결됨');
916
+
917
+ ws.on('message', async (data) => {
918
+ let message: any;
919
+ try {
920
+ message = JSON.parse(data.toString());
921
+
922
+ if (message.method === 'tools/list') {
923
+ const toolRegistry = getToolRegistry();
924
+ const tools = toolRegistry.getAll();
925
+
926
+ ws.send(JSON.stringify({
927
+ jsonrpc: '2.0',
928
+ id: message.id,
929
+ result: { tools }
930
+ }));
931
+ } else if (message.method === 'tools/call') {
932
+ const { name, arguments: args } = message.params;
933
+
934
+ const toolRegistry = getToolRegistry();
935
+
936
+ // 도ꡬ μ»¨ν…μŠ€νŠΈ 생성
937
+ const context: ToolContext = {
938
+ db,
939
+ services: {
940
+ searchEngine,
941
+ hybridSearchEngine,
942
+ embeddingService
943
+ }
944
+ };
945
+
946
+ // 도ꡬ μ‹€ν–‰
947
+ const result = await toolRegistry.execute(name, args, context);
948
+
949
+ ws.send(JSON.stringify({
950
+ jsonrpc: '2.0',
951
+ id: message.id,
952
+ result: { content: [{ type: 'text', text: JSON.stringify(result) }] }
953
+ }));
954
+ }
955
+ } catch (error) {
956
+ console.error('❌ WebSocket λ©”μ‹œμ§€ 처리 μ‹€νŒ¨:', error);
957
+ ws.send(JSON.stringify({
958
+ jsonrpc: '2.0',
959
+ id: message?.id || null,
960
+ error: {
961
+ code: -32603,
962
+ message: 'Internal error',
963
+ data: error instanceof Error ? error.message : 'Unknown error'
964
+ }
965
+ }));
966
+ }
967
+ });
968
+
969
+ ws.on('close', () => {
970
+ console.log('πŸ”Œ WebSocket ν΄λΌμ΄μ–ΈνŠΈ μ—°κ²° ν•΄μ œλ¨');
971
+ });
972
+
973
+ ws.on('error', (error) => {
974
+ console.error('❌ WebSocket μ—λŸ¬:', error);
975
+ });
976
+ });
977
+
978
+ // μ„œλ²„ μ‹œμž‘
979
+ const PORT = process.env.PORT || 9001;
980
+
981
+ async function startServer() {
982
+ await initializeServer();
983
+
984
+ // 정리 ν•Έλ“€λŸ¬ 등둝
985
+ registerCleanupHandlers();
986
+
987
+ // Express app을 μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  μΈν„°νŽ˜μ΄μŠ€μ— 바인딩
988
+ app.listen(Number(PORT), '0.0.0.0', () => {
989
+ console.log(`🌐 HTTP μ„œλ²„: http://0.0.0.0:${PORT}`);
990
+ console.log(`πŸ”Œ WebSocket μ„œλ²„: ws://0.0.0.0:${PORT}`);
991
+ console.log(`πŸ“‹ API λ¬Έμ„œ: http://0.0.0.0:${PORT}/tools`);
992
+ console.log(`❀️ ν—¬μŠ€ 체크: http://0.0.0.0:${PORT}/health`);
993
+ });
994
+
995
+ // μΆ”κ°€: λͺ¨λ“  μΈν„°νŽ˜μ΄μŠ€μ— 바인딩 확인
996
+ server.on('listening', () => {
997
+ const address = server.address();
998
+ if (address && typeof address === 'object') {
999
+ console.log(`πŸ”— μ„œλ²„κ°€ ${address.address}:${address.port}에 바인딩됨`);
1000
+ }
1001
+ });
1002
+ }
1003
+
1004
+ // μ„œλ²„ μ‹œμž‘
1005
+ if (process.argv[1] && (process.argv[1].includes('http-server'))) {
1006
+ startServer().catch(error => {
1007
+ console.error('❌ μ„œλ²„ μ‹œμž‘ μ‹€νŒ¨:', error);
1008
+ process.exit(1);
1009
+ });
1010
+ }
1011
+
1012
+ export const __test: {
1013
+ setTestDependencies: (deps: TestDependencies) => void;
1014
+ getApp: () => express.Application;
1015
+ getServer: () => any;
1016
+ getDatabase: () => Database.Database | null;
1017
+ getSearchEngine: () => SearchEngine | undefined;
1018
+ getHybridSearchEngine: () => HybridSearchEngine | undefined;
1019
+ getEmbeddingService: () => MemoryEmbeddingService | undefined;
1020
+ } = {
1021
+ setTestDependencies,
1022
+ getApp: () => app,
1023
+ getServer: () => server,
1024
+ getDatabase: () => db,
1025
+ getSearchEngine: () => searchEngine,
1026
+ getHybridSearchEngine: () => hybridSearchEngine,
1027
+ getEmbeddingService: () => embeddingService
1028
+ };
1029
+
1030
+ export { startServer, cleanup };