@mongrov/analytics 0.1.0-alpha.0 → 0.1.0-alpha.10

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 (348) hide show
  1. package/README.md +472 -0
  2. package/dist/core/context.d.ts +24 -0
  3. package/dist/core/context.d.ts.map +1 -0
  4. package/dist/core/context.js +30 -0
  5. package/dist/core/context.js.map +1 -0
  6. package/dist/core/engine.d.ts +56 -0
  7. package/dist/core/engine.d.ts.map +1 -0
  8. package/dist/core/engine.js +119 -0
  9. package/dist/core/engine.js.map +1 -0
  10. package/dist/core/errors.d.ts +1 -1
  11. package/dist/core/errors.d.ts.map +1 -1
  12. package/dist/core/errors.js.map +1 -1
  13. package/dist/core/extensions.d.ts +33 -0
  14. package/dist/core/extensions.d.ts.map +1 -0
  15. package/dist/core/extensions.js +58 -0
  16. package/dist/core/extensions.js.map +1 -0
  17. package/dist/core/factory.d.ts +22 -5
  18. package/dist/core/factory.d.ts.map +1 -1
  19. package/dist/core/factory.js +231 -6
  20. package/dist/core/factory.js.map +1 -1
  21. package/dist/core/hooks.d.ts +32 -13
  22. package/dist/core/hooks.d.ts.map +1 -1
  23. package/dist/core/hooks.js +137 -15
  24. package/dist/core/hooks.js.map +1 -1
  25. package/dist/core/index.d.ts +3 -0
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/index.js +3 -1
  28. package/dist/core/index.js.map +1 -1
  29. package/dist/core/logger.d.ts +25 -0
  30. package/dist/core/logger.d.ts.map +1 -0
  31. package/dist/core/logger.js +33 -0
  32. package/dist/core/logger.js.map +1 -0
  33. package/dist/core/machine.d.ts +174 -0
  34. package/dist/core/machine.d.ts.map +1 -0
  35. package/dist/core/machine.js +228 -0
  36. package/dist/core/machine.js.map +1 -0
  37. package/dist/core/metric_metadata.d.ts +128 -0
  38. package/dist/core/metric_metadata.d.ts.map +1 -0
  39. package/dist/core/metric_metadata.js +47 -0
  40. package/dist/core/metric_metadata.js.map +1 -0
  41. package/dist/core/migrations.d.ts +52 -0
  42. package/dist/core/migrations.d.ts.map +1 -0
  43. package/dist/core/migrations.js +66 -0
  44. package/dist/core/migrations.js.map +1 -0
  45. package/dist/core/persistence.d.ts +50 -0
  46. package/dist/core/persistence.d.ts.map +1 -0
  47. package/dist/core/persistence.js +80 -0
  48. package/dist/core/persistence.js.map +1 -0
  49. package/dist/core/retention.d.ts +90 -0
  50. package/dist/core/retention.d.ts.map +1 -0
  51. package/dist/core/retention.js +119 -0
  52. package/dist/core/retention.js.map +1 -0
  53. package/dist/core/schemas.d.ts +35 -0
  54. package/dist/core/schemas.d.ts.map +1 -0
  55. package/dist/core/schemas.js +209 -0
  56. package/dist/core/schemas.js.map +1 -0
  57. package/dist/core/types.d.ts +10 -0
  58. package/dist/core/types.d.ts.map +1 -1
  59. package/dist/core/warehouse.d.ts +58 -0
  60. package/dist/core/warehouse.d.ts.map +1 -0
  61. package/dist/core/warehouse.js +116 -0
  62. package/dist/core/warehouse.js.map +1 -0
  63. package/dist/rules/__fakes__/fakeClock.d.ts +7 -0
  64. package/dist/rules/__fakes__/fakeClock.d.ts.map +1 -0
  65. package/dist/rules/__fakes__/fakeClock.js +13 -0
  66. package/dist/rules/__fakes__/fakeClock.js.map +1 -0
  67. package/dist/rules/__fakes__/fakeEngine.d.ts +12 -0
  68. package/dist/rules/__fakes__/fakeEngine.d.ts.map +1 -0
  69. package/dist/rules/__fakes__/fakeEngine.js +33 -0
  70. package/dist/rules/__fakes__/fakeEngine.js.map +1 -0
  71. package/dist/rules/__fakes__/fakeStorage.d.ts +7 -0
  72. package/dist/rules/__fakes__/fakeStorage.d.ts.map +1 -0
  73. package/dist/rules/__fakes__/fakeStorage.js +22 -0
  74. package/dist/rules/__fakes__/fakeStorage.js.map +1 -0
  75. package/dist/rules/compiler-cache.d.ts +16 -0
  76. package/dist/rules/compiler-cache.d.ts.map +1 -0
  77. package/dist/rules/compiler-cache.js +29 -0
  78. package/dist/rules/compiler-cache.js.map +1 -0
  79. package/dist/rules/compiler.d.ts +27 -0
  80. package/dist/rules/compiler.d.ts.map +1 -0
  81. package/dist/rules/compiler.js +210 -0
  82. package/dist/rules/compiler.js.map +1 -0
  83. package/dist/rules/defaults/index.d.ts +13 -0
  84. package/dist/rules/defaults/index.d.ts.map +1 -0
  85. package/dist/rules/defaults/index.js +13 -0
  86. package/dist/rules/defaults/index.js.map +1 -0
  87. package/dist/rules/defaults/loader.d.ts +18 -0
  88. package/dist/rules/defaults/loader.d.ts.map +1 -0
  89. package/dist/rules/defaults/loader.js +37 -0
  90. package/dist/rules/defaults/loader.js.map +1 -0
  91. package/dist/rules/defaults/luminx.d.ts +6 -0
  92. package/dist/rules/defaults/luminx.d.ts.map +1 -0
  93. package/dist/rules/defaults/luminx.js +64 -0
  94. package/dist/rules/defaults/luminx.js.map +1 -0
  95. package/dist/rules/defaults/viva.d.ts +6 -0
  96. package/dist/rules/defaults/viva.d.ts.map +1 -0
  97. package/dist/rules/defaults/viva.js +45 -0
  98. package/dist/rules/defaults/viva.js.map +1 -0
  99. package/dist/rules/defaults/yogaring.d.ts +6 -0
  100. package/dist/rules/defaults/yogaring.d.ts.map +1 -0
  101. package/dist/rules/defaults/yogaring.js +45 -0
  102. package/dist/rules/defaults/yogaring.js.map +1 -0
  103. package/dist/rules/defaults/ziva.d.ts +10 -0
  104. package/dist/rules/defaults/ziva.d.ts.map +1 -0
  105. package/dist/rules/defaults/ziva.js +87 -0
  106. package/dist/rules/defaults/ziva.js.map +1 -0
  107. package/dist/rules/emitter.d.ts +20 -0
  108. package/dist/rules/emitter.d.ts.map +1 -0
  109. package/dist/rules/emitter.js +32 -0
  110. package/dist/rules/emitter.js.map +1 -0
  111. package/dist/rules/evaluator.d.ts +44 -0
  112. package/dist/rules/evaluator.d.ts.map +1 -0
  113. package/dist/rules/evaluator.js +127 -0
  114. package/dist/rules/evaluator.js.map +1 -0
  115. package/dist/rules/factory.d.ts +13 -0
  116. package/dist/rules/factory.d.ts.map +1 -0
  117. package/dist/rules/factory.js +56 -0
  118. package/dist/rules/factory.js.map +1 -0
  119. package/dist/rules/hooks/useRuleRegistry.d.ts +16 -0
  120. package/dist/rules/hooks/useRuleRegistry.d.ts.map +1 -0
  121. package/dist/rules/hooks/useRuleRegistry.js +26 -0
  122. package/dist/rules/hooks/useRuleRegistry.js.map +1 -0
  123. package/dist/rules/hooks/useRuleViolations.d.ts +21 -0
  124. package/dist/rules/hooks/useRuleViolations.d.ts.map +1 -0
  125. package/dist/rules/hooks/useRuleViolations.js +32 -0
  126. package/dist/rules/hooks/useRuleViolations.js.map +1 -0
  127. package/dist/rules/index.d.ts +30 -1
  128. package/dist/rules/index.d.ts.map +1 -1
  129. package/dist/rules/index.js +36 -1
  130. package/dist/rules/index.js.map +1 -1
  131. package/dist/rules/registry.d.ts +32 -0
  132. package/dist/rules/registry.d.ts.map +1 -0
  133. package/dist/rules/registry.js +98 -0
  134. package/dist/rules/registry.js.map +1 -0
  135. package/dist/rules/schema.d.ts +221 -0
  136. package/dist/rules/schema.d.ts.map +1 -0
  137. package/dist/rules/schema.js +80 -0
  138. package/dist/rules/schema.js.map +1 -0
  139. package/dist/rules/throttle.d.ts +27 -0
  140. package/dist/rules/throttle.d.ts.map +1 -0
  141. package/dist/rules/throttle.js +76 -0
  142. package/dist/rules/throttle.js.map +1 -0
  143. package/dist/rules/types.d.ts +88 -0
  144. package/dist/rules/types.d.ts.map +1 -0
  145. package/dist/rules/types.js +9 -0
  146. package/dist/rules/types.js.map +1 -0
  147. package/dist/rules/validator.d.ts +27 -0
  148. package/dist/rules/validator.d.ts.map +1 -0
  149. package/dist/rules/validator.js +97 -0
  150. package/dist/rules/validator.js.map +1 -0
  151. package/dist/sync/buffer.d.ts +51 -0
  152. package/dist/sync/buffer.d.ts.map +1 -0
  153. package/dist/sync/buffer.js +188 -0
  154. package/dist/sync/buffer.js.map +1 -0
  155. package/dist/sync/context.d.ts +17 -0
  156. package/dist/sync/context.d.ts.map +1 -0
  157. package/dist/sync/context.js +23 -0
  158. package/dist/sync/context.js.map +1 -0
  159. package/dist/sync/errors.d.ts +19 -0
  160. package/dist/sync/errors.d.ts.map +1 -0
  161. package/dist/sync/errors.js +21 -0
  162. package/dist/sync/errors.js.map +1 -0
  163. package/dist/sync/events.d.ts +49 -0
  164. package/dist/sync/events.d.ts.map +1 -0
  165. package/dist/sync/events.js +46 -0
  166. package/dist/sync/events.js.map +1 -0
  167. package/dist/sync/factory.d.ts +65 -0
  168. package/dist/sync/factory.d.ts.map +1 -0
  169. package/dist/sync/factory.js +279 -0
  170. package/dist/sync/factory.js.map +1 -0
  171. package/dist/sync/fetcher.d.ts +74 -0
  172. package/dist/sync/fetcher.d.ts.map +1 -0
  173. package/dist/sync/fetcher.js +166 -0
  174. package/dist/sync/fetcher.js.map +1 -0
  175. package/dist/sync/flusher.d.ts +99 -0
  176. package/dist/sync/flusher.d.ts.map +1 -0
  177. package/dist/sync/flusher.js +246 -0
  178. package/dist/sync/flusher.js.map +1 -0
  179. package/dist/sync/hooks.d.ts +17 -0
  180. package/dist/sync/hooks.d.ts.map +1 -0
  181. package/dist/sync/hooks.js +48 -0
  182. package/dist/sync/hooks.js.map +1 -0
  183. package/dist/sync/index.d.ts +32 -1
  184. package/dist/sync/index.d.ts.map +1 -1
  185. package/dist/sync/index.js +36 -1
  186. package/dist/sync/index.js.map +1 -1
  187. package/dist/sync/manager.d.ts +48 -0
  188. package/dist/sync/manager.d.ts.map +1 -0
  189. package/dist/sync/manager.js +9 -0
  190. package/dist/sync/manager.js.map +1 -0
  191. package/dist/sync/mapper/activity.d.ts +31 -0
  192. package/dist/sync/mapper/activity.d.ts.map +1 -0
  193. package/dist/sync/mapper/activity.js +56 -0
  194. package/dist/sync/mapper/activity.js.map +1 -0
  195. package/dist/sync/mapper/battery.d.ts +12 -0
  196. package/dist/sync/mapper/battery.d.ts.map +1 -0
  197. package/dist/sync/mapper/battery.js +22 -0
  198. package/dist/sync/mapper/battery.js.map +1 -0
  199. package/dist/sync/mapper/firmware.d.ts +28 -0
  200. package/dist/sync/mapper/firmware.d.ts.map +1 -0
  201. package/dist/sync/mapper/firmware.js +43 -0
  202. package/dist/sync/mapper/firmware.js.map +1 -0
  203. package/dist/sync/mapper/heart-rate.d.ts +10 -0
  204. package/dist/sync/mapper/heart-rate.d.ts.map +1 -0
  205. package/dist/sync/mapper/heart-rate.js +19 -0
  206. package/dist/sync/mapper/heart-rate.js.map +1 -0
  207. package/dist/sync/mapper/hrv.d.ts +22 -0
  208. package/dist/sync/mapper/hrv.d.ts.map +1 -0
  209. package/dist/sync/mapper/hrv.js +56 -0
  210. package/dist/sync/mapper/hrv.js.map +1 -0
  211. package/dist/sync/mapper/ring-config.d.ts +33 -0
  212. package/dist/sync/mapper/ring-config.d.ts.map +1 -0
  213. package/dist/sync/mapper/ring-config.js +48 -0
  214. package/dist/sync/mapper/ring-config.js.map +1 -0
  215. package/dist/sync/mapper/sleep.d.ts +32 -0
  216. package/dist/sync/mapper/sleep.d.ts.map +1 -0
  217. package/dist/sync/mapper/sleep.js +103 -0
  218. package/dist/sync/mapper/sleep.js.map +1 -0
  219. package/dist/sync/mapper/spo2.d.ts +9 -0
  220. package/dist/sync/mapper/spo2.d.ts.map +1 -0
  221. package/dist/sync/mapper/spo2.js +18 -0
  222. package/dist/sync/mapper/spo2.js.map +1 -0
  223. package/dist/sync/mapper/temperature.d.ts +10 -0
  224. package/dist/sync/mapper/temperature.d.ts.map +1 -0
  225. package/dist/sync/mapper/temperature.js +19 -0
  226. package/dist/sync/mapper/temperature.js.map +1 -0
  227. package/dist/sync/mapper/time.d.ts +49 -0
  228. package/dist/sync/mapper/time.d.ts.map +1 -0
  229. package/dist/sync/mapper/time.js +107 -0
  230. package/dist/sync/mapper/time.js.map +1 -0
  231. package/dist/sync/mapper/types.d.ts +152 -0
  232. package/dist/sync/mapper/types.d.ts.map +1 -0
  233. package/dist/sync/mapper/types.js +15 -0
  234. package/dist/sync/mapper/types.js.map +1 -0
  235. package/dist/sync/overflow.d.ts +30 -0
  236. package/dist/sync/overflow.d.ts.map +1 -0
  237. package/dist/sync/overflow.js +114 -0
  238. package/dist/sync/overflow.js.map +1 -0
  239. package/dist/sync/pusher.d.ts +59 -0
  240. package/dist/sync/pusher.d.ts.map +1 -0
  241. package/dist/sync/pusher.js +115 -0
  242. package/dist/sync/pusher.js.map +1 -0
  243. package/dist/sync/scheduler.d.ts +84 -0
  244. package/dist/sync/scheduler.d.ts.map +1 -0
  245. package/dist/sync/scheduler.js +132 -0
  246. package/dist/sync/scheduler.js.map +1 -0
  247. package/dist/sync/triggers.d.ts +64 -0
  248. package/dist/sync/triggers.d.ts.map +1 -0
  249. package/dist/sync/triggers.js +113 -0
  250. package/dist/sync/triggers.js.map +1 -0
  251. package/dist/sync/types.d.ts +50 -0
  252. package/dist/sync/types.d.ts.map +1 -0
  253. package/dist/sync/types.js +8 -0
  254. package/dist/sync/types.js.map +1 -0
  255. package/dist/sync/watermark.d.ts +32 -0
  256. package/dist/sync/watermark.d.ts.map +1 -0
  257. package/dist/sync/watermark.js +61 -0
  258. package/dist/sync/watermark.js.map +1 -0
  259. package/dist/tools/__fakes__/engine.d.ts +25 -0
  260. package/dist/tools/__fakes__/engine.d.ts.map +1 -0
  261. package/dist/tools/__fakes__/engine.js +37 -0
  262. package/dist/tools/__fakes__/engine.js.map +1 -0
  263. package/dist/tools/audit.d.ts +31 -0
  264. package/dist/tools/audit.d.ts.map +1 -0
  265. package/dist/tools/audit.js +157 -0
  266. package/dist/tools/audit.js.map +1 -0
  267. package/dist/tools/authorize.d.ts +36 -0
  268. package/dist/tools/authorize.d.ts.map +1 -0
  269. package/dist/tools/authorize.js +87 -0
  270. package/dist/tools/authorize.js.map +1 -0
  271. package/dist/tools/budget.d.ts +15 -0
  272. package/dist/tools/budget.d.ts.map +1 -0
  273. package/dist/tools/budget.js +64 -0
  274. package/dist/tools/budget.js.map +1 -0
  275. package/dist/tools/factory.d.ts +43 -0
  276. package/dist/tools/factory.d.ts.map +1 -0
  277. package/dist/tools/factory.js +137 -0
  278. package/dist/tools/factory.js.map +1 -0
  279. package/dist/tools/formatters.d.ts +17 -0
  280. package/dist/tools/formatters.d.ts.map +1 -0
  281. package/dist/tools/formatters.js +30 -0
  282. package/dist/tools/formatters.js.map +1 -0
  283. package/dist/tools/impls/activity.d.ts +15 -0
  284. package/dist/tools/impls/activity.d.ts.map +1 -0
  285. package/dist/tools/impls/activity.js +61 -0
  286. package/dist/tools/impls/activity.js.map +1 -0
  287. package/dist/tools/impls/anomaly.d.ts +21 -0
  288. package/dist/tools/impls/anomaly.d.ts.map +1 -0
  289. package/dist/tools/impls/anomaly.js +70 -0
  290. package/dist/tools/impls/anomaly.js.map +1 -0
  291. package/dist/tools/impls/compare.d.ts +21 -0
  292. package/dist/tools/impls/compare.d.ts.map +1 -0
  293. package/dist/tools/impls/compare.js +68 -0
  294. package/dist/tools/impls/compare.js.map +1 -0
  295. package/dist/tools/impls/hrv.d.ts +15 -0
  296. package/dist/tools/impls/hrv.d.ts.map +1 -0
  297. package/dist/tools/impls/hrv.js +36 -0
  298. package/dist/tools/impls/hrv.js.map +1 -0
  299. package/dist/tools/impls/insights.d.ts +18 -0
  300. package/dist/tools/impls/insights.d.ts.map +1 -0
  301. package/dist/tools/impls/insights.js +41 -0
  302. package/dist/tools/impls/insights.js.map +1 -0
  303. package/dist/tools/impls/sleep.d.ts +15 -0
  304. package/dist/tools/impls/sleep.d.ts.map +1 -0
  305. package/dist/tools/impls/sleep.js +43 -0
  306. package/dist/tools/impls/sleep.js.map +1 -0
  307. package/dist/tools/index.d.ts +13 -1
  308. package/dist/tools/index.d.ts.map +1 -1
  309. package/dist/tools/index.js +21 -1
  310. package/dist/tools/index.js.map +1 -1
  311. package/dist/tools/mcp/adapter.d.ts +33 -0
  312. package/dist/tools/mcp/adapter.d.ts.map +1 -0
  313. package/dist/tools/mcp/adapter.js +56 -0
  314. package/dist/tools/mcp/adapter.js.map +1 -0
  315. package/dist/tools/mcp/guard.d.ts +17 -0
  316. package/dist/tools/mcp/guard.d.ts.map +1 -0
  317. package/dist/tools/mcp/guard.js +22 -0
  318. package/dist/tools/mcp/guard.js.map +1 -0
  319. package/dist/tools/mcp/index.d.ts +20 -0
  320. package/dist/tools/mcp/index.d.ts.map +1 -0
  321. package/dist/tools/mcp/index.js +16 -0
  322. package/dist/tools/mcp/index.js.map +1 -0
  323. package/dist/tools/mcp/server.d.ts +39 -0
  324. package/dist/tools/mcp/server.d.ts.map +1 -0
  325. package/dist/tools/mcp/server.js +70 -0
  326. package/dist/tools/mcp/server.js.map +1 -0
  327. package/dist/tools/mcp/transports/http.d.ts +54 -0
  328. package/dist/tools/mcp/transports/http.d.ts.map +1 -0
  329. package/dist/tools/mcp/transports/http.js +133 -0
  330. package/dist/tools/mcp/transports/http.js.map +1 -0
  331. package/dist/tools/mcp/transports/stdio.d.ts +22 -0
  332. package/dist/tools/mcp/transports/stdio.d.ts.map +1 -0
  333. package/dist/tools/mcp/transports/stdio.js +19 -0
  334. package/dist/tools/mcp/transports/stdio.js.map +1 -0
  335. package/dist/tools/rate-limit.d.ts +26 -0
  336. package/dist/tools/rate-limit.d.ts.map +1 -0
  337. package/dist/tools/rate-limit.js +67 -0
  338. package/dist/tools/rate-limit.js.map +1 -0
  339. package/dist/tools/types.d.ts +121 -0
  340. package/dist/tools/types.d.ts.map +1 -0
  341. package/dist/tools/types.js +16 -0
  342. package/dist/tools/types.js.map +1 -0
  343. package/dist/tools/wrap.d.ts +53 -0
  344. package/dist/tools/wrap.d.ts.map +1 -0
  345. package/dist/tools/wrap.js +135 -0
  346. package/dist/tools/wrap.js.map +1 -0
  347. package/package.json +43 -16
  348. package/LICENSE +0 -21
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `toMcpTools` — adapt the six wrapped AI SDK v4 tools that back
3
+ * `AnalyticsToolsHandle` into the shape MCP servers speak.
4
+ *
5
+ * MCP servers want `{ name, description, inputSchema (JSON Schema),
6
+ * handler(args) => { content: [{ type: 'text', text }] } }`. Our
7
+ * factory returns AI SDK v4 tools whose `execute(args, opts) =>
8
+ * Promise<string>` already runs the full
9
+ * rate → auth → execute → budget → audit chain — so the adapter is
10
+ * a thin translation layer, not a second wrapper.
11
+ *
12
+ * The Zod parameter schemas are converted to JSON Schema draft-7 via
13
+ * `zod-to-json-schema` (drops `$schema` and `additionalProperties`
14
+ * so MCP clients get a compact tool descriptor). `.default()` values
15
+ * survive the conversion (asserted in the tests) so LLMs see the
16
+ * documented defaults on `detectAnomaly.stddevThreshold` and
17
+ * `getInsights.days`.
18
+ */
19
+ import type { AnalyticsToolsHandle } from '../factory';
20
+ export interface McpTool {
21
+ name: string;
22
+ description: string;
23
+ inputSchema: Record<string, unknown>;
24
+ handler: (args: unknown) => Promise<{
25
+ content: {
26
+ type: 'text';
27
+ text: string;
28
+ }[];
29
+ isError?: boolean;
30
+ }>;
31
+ }
32
+ export declare function toMcpTools(handle: AnalyticsToolsHandle): McpTool[];
33
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;QAClC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;QACzC,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAC,CAAA;CACH;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,EAAE,CAyClE"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `toMcpTools` — adapt the six wrapped AI SDK v4 tools that back
3
+ * `AnalyticsToolsHandle` into the shape MCP servers speak.
4
+ *
5
+ * MCP servers want `{ name, description, inputSchema (JSON Schema),
6
+ * handler(args) => { content: [{ type: 'text', text }] } }`. Our
7
+ * factory returns AI SDK v4 tools whose `execute(args, opts) =>
8
+ * Promise<string>` already runs the full
9
+ * rate → auth → execute → budget → audit chain — so the adapter is
10
+ * a thin translation layer, not a second wrapper.
11
+ *
12
+ * The Zod parameter schemas are converted to JSON Schema draft-7 via
13
+ * `zod-to-json-schema` (drops `$schema` and `additionalProperties`
14
+ * so MCP clients get a compact tool descriptor). `.default()` values
15
+ * survive the conversion (asserted in the tests) so LLMs see the
16
+ * documented defaults on `detectAnomaly.stddevThreshold` and
17
+ * `getInsights.days`.
18
+ */
19
+ import { zodToJsonSchema } from 'zod-to-json-schema';
20
+ export function toMcpTools(handle) {
21
+ const entries = Object.entries(handle.tools);
22
+ return entries.map(([name, tool]) => {
23
+ const parameters = tool.parameters;
24
+ const rawSchema = zodToJsonSchema(parameters, {
25
+ target: 'jsonSchema7',
26
+ $refStrategy: 'none',
27
+ });
28
+ // Strip the top-level $schema marker — MCP clients don't need it,
29
+ // and its presence bloats every list_tools response.
30
+ const { $schema: _drop, ...inputSchema } = rawSchema;
31
+ return {
32
+ name: String(name),
33
+ description: tool.description ?? '',
34
+ inputSchema,
35
+ handler: async (args) => {
36
+ if (!tool.execute) {
37
+ return {
38
+ content: [{
39
+ type: 'text',
40
+ text: `Tool ${String(name)} is not executable.`,
41
+ }],
42
+ isError: true,
43
+ };
44
+ }
45
+ const text = await tool.execute(args, {
46
+ toolCallId: `mcp:${String(name)}`,
47
+ messages: [],
48
+ });
49
+ return {
50
+ content: [{ type: 'text', text: String(text) }],
51
+ };
52
+ },
53
+ };
54
+ });
55
+ }
56
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/tools/mcp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAapD,MAAM,UAAU,UAAU,CAAC,MAA4B;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAGxC,CAAA;IAEH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAmD,CAAA;QAC3E,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,EAAE;YAC5C,MAAM,EAAE,aAAa;YACrB,YAAY,EAAE,MAAM;SACrB,CAA4B,CAAA;QAE7B,kEAAkE;QAClE,qDAAqD;QACrD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,SAAS,CAAA;QAEpD,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;YACnC,WAAW;YACX,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;gBAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClB,OAAO;wBACL,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,QAAQ,MAAM,CAAC,IAAI,CAAC,qBAAqB;6BAChD,CAAC;wBACF,OAAO,EAAE,IAAI;qBACd,CAAA;gBACH,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAa,EAAE;oBAC7C,UAAU,EAAE,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE;oBACjC,QAAQ,EAAE,EAAE;iBACb,CAAC,CAAA;gBACF,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;iBACzD,CAAA;YACH,CAAC;SACF,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `shouldStartMcpServer` — cross-runtime dev flag for the MCP subpath.
3
+ *
4
+ * Returns `true` iff the process is a React Native dev build
5
+ * (`__DEV__ === true`) **or** the Node process has
6
+ * `ENABLE_MCP_SERVER=1` set. Prod RN builds have `__DEV__ === false`
7
+ * and no `process.env`, so the check returns `false` and the caller
8
+ * short-circuits — with `sideEffects: false` at the package root,
9
+ * this lets bundlers drop every module reachable only through the
10
+ * MCP subpath (including `@modelcontextprotocol/sdk`).
11
+ *
12
+ * The helper is intentionally pure — importing it does not itself
13
+ * import the SDK. Callers should gate SDK imports behind
14
+ * `shouldStartMcpServer()` at their entry point.
15
+ */
16
+ export declare function shouldStartMcpServer(): boolean;
17
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `shouldStartMcpServer` — cross-runtime dev flag for the MCP subpath.
3
+ *
4
+ * Returns `true` iff the process is a React Native dev build
5
+ * (`__DEV__ === true`) **or** the Node process has
6
+ * `ENABLE_MCP_SERVER=1` set. Prod RN builds have `__DEV__ === false`
7
+ * and no `process.env`, so the check returns `false` and the caller
8
+ * short-circuits — with `sideEffects: false` at the package root,
9
+ * this lets bundlers drop every module reachable only through the
10
+ * MCP subpath (including `@modelcontextprotocol/sdk`).
11
+ *
12
+ * The helper is intentionally pure — importing it does not itself
13
+ * import the SDK. Callers should gate SDK imports behind
14
+ * `shouldStartMcpServer()` at their entry point.
15
+ */
16
+ export function shouldStartMcpServer() {
17
+ const isRnDev = typeof __DEV__ !== 'undefined' && __DEV__ === true;
18
+ const isNodeFlag = typeof process !== 'undefined'
19
+ && process.env?.ENABLE_MCP_SERVER === '1';
20
+ return isRnDev || isNodeFlag;
21
+ }
22
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/tools/mcp/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GACT,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,CAAA;IACtD,MAAM,UAAU,GACZ,OAAO,OAAO,KAAK,WAAW;WAC3B,OAAO,CAAC,GAAG,EAAE,iBAAiB,KAAK,GAAG,CAAA;IAC7C,OAAO,OAAO,IAAI,UAAU,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `@mongrov/analytics/tools/mcp` — Model Context Protocol server for
3
+ * the six analytics tools. See `./README.md` for wiring examples.
4
+ *
5
+ * Importing this barrel does NOT itself construct a server. Callers
6
+ * gate SDK-touching code behind `shouldStartMcpServer()`; combined
7
+ * with the package's `sideEffects: false`, prod bundles reachable
8
+ * only through this subpath drop the `@modelcontextprotocol/sdk`
9
+ * runtime entirely.
10
+ */
11
+ export { toMcpTools } from './adapter';
12
+ export type { McpTool } from './adapter';
13
+ export { shouldStartMcpServer } from './guard';
14
+ export { createMcpServer } from './server';
15
+ export type { CreateMcpServerConfig, McpServerHandle, } from './server';
16
+ export { createStdioTransport } from './transports/stdio';
17
+ export type { CreateStdioTransportOptions } from './transports/stdio';
18
+ export { createHttpTransport } from './transports/http';
19
+ export type { CreateHttpTransportConfig, HttpTransportHandle, } from './transports/http';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACV,qBAAqB,EACrB,eAAe,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,YAAY,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EACV,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@mongrov/analytics/tools/mcp` — Model Context Protocol server for
3
+ * the six analytics tools. See `./README.md` for wiring examples.
4
+ *
5
+ * Importing this barrel does NOT itself construct a server. Callers
6
+ * gate SDK-touching code behind `shouldStartMcpServer()`; combined
7
+ * with the package's `sideEffects: false`, prod bundles reachable
8
+ * only through this subpath drop the `@modelcontextprotocol/sdk`
9
+ * runtime entirely.
10
+ */
11
+ export { toMcpTools } from './adapter';
12
+ export { shouldStartMcpServer } from './guard';
13
+ export { createMcpServer } from './server';
14
+ export { createStdioTransport } from './transports/stdio';
15
+ export { createHttpTransport } from './transports/http';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAM1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `createMcpServer` — wrap an `AnalyticsToolsHandle` in an MCP server
3
+ * that speaks `tools/list` + `tools/call` to any MCP client.
4
+ *
5
+ * We use the low-level `Server` + `setRequestHandler` rather than the
6
+ * higher-level `McpServer.registerTool`, because `registerTool` wants
7
+ * either a Zod raw shape or an `AnySchema`, and our tools were built
8
+ * around `zod.object(...)` (not raw shapes) and are already converted
9
+ * to JSON Schema by `toMcpTools`. Emitting the pre-baked JSON Schema
10
+ * from `tools/list` keeps the source of truth in one place (the Zod
11
+ * schemas in `src/tools/impls/*.ts`).
12
+ *
13
+ * `call_tool` re-dispatches into the wrapped `tool.execute`, which
14
+ * runs the full rate → auth → execute → budget → audit chain via the
15
+ * ctx container the handle owns. `handle.setContext(...)` before an
16
+ * MCP session behaves identically to setting it before an AI SDK turn.
17
+ */
18
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
19
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
20
+ import type { AnalyticsToolsHandle } from '../factory';
21
+ import type { ToolsLogger } from '../types';
22
+ export interface CreateMcpServerConfig {
23
+ toolsHandle: AnalyticsToolsHandle;
24
+ /** Server name advertised on `initialize`. Default `'mongrov-analytics'`. */
25
+ name?: string;
26
+ /** Server version advertised on `initialize`. Default `'0.1.0'`. */
27
+ version?: string;
28
+ logger?: ToolsLogger;
29
+ }
30
+ export interface McpServerHandle {
31
+ /** The underlying SDK server — exposed for advanced callers. */
32
+ server: Server;
33
+ /** Attach to a transport and start listening. */
34
+ connect: (transport: Transport) => Promise<void>;
35
+ /** Close the connection. Does NOT close the underlying tools handle. */
36
+ close: () => Promise<void>;
37
+ }
38
+ export declare function createMcpServer(config: CreateMcpServerConfig): McpServerHandle;
39
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAK9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAG3C,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,oBAAoB,CAAA;IACjC,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,wEAAwE;IACxE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CA2DjB"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * `createMcpServer` — wrap an `AnalyticsToolsHandle` in an MCP server
3
+ * that speaks `tools/list` + `tools/call` to any MCP client.
4
+ *
5
+ * We use the low-level `Server` + `setRequestHandler` rather than the
6
+ * higher-level `McpServer.registerTool`, because `registerTool` wants
7
+ * either a Zod raw shape or an `AnySchema`, and our tools were built
8
+ * around `zod.object(...)` (not raw shapes) and are already converted
9
+ * to JSON Schema by `toMcpTools`. Emitting the pre-baked JSON Schema
10
+ * from `tools/list` keeps the source of truth in one place (the Zod
11
+ * schemas in `src/tools/impls/*.ts`).
12
+ *
13
+ * `call_tool` re-dispatches into the wrapped `tool.execute`, which
14
+ * runs the full rate → auth → execute → budget → audit chain via the
15
+ * ctx container the handle owns. `handle.setContext(...)` before an
16
+ * MCP session behaves identically to setting it before an AI SDK turn.
17
+ */
18
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
19
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
20
+ import { toMcpTools } from './adapter';
21
+ export function createMcpServer(config) {
22
+ const mcpTools = toMcpTools(config.toolsHandle);
23
+ const byName = new Map(mcpTools.map(t => [t.name, t]));
24
+ const server = new Server({
25
+ name: config.name ?? 'mongrov-analytics',
26
+ version: config.version ?? '0.1.0',
27
+ }, { capabilities: { tools: {} } });
28
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
29
+ tools: mcpTools.map(t => ({
30
+ name: t.name,
31
+ description: t.description,
32
+ inputSchema: t.inputSchema,
33
+ })),
34
+ }));
35
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
36
+ const tool = byName.get(req.params.name);
37
+ if (!tool) {
38
+ return {
39
+ content: [{
40
+ type: 'text',
41
+ text: `Unknown tool: ${req.params.name}`,
42
+ }],
43
+ isError: true,
44
+ };
45
+ }
46
+ try {
47
+ return await tool.handler(req.params.arguments ?? {});
48
+ }
49
+ catch (err) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ config.logger?.error('mcp tool handler threw', {
52
+ toolName: req.params.name,
53
+ err: message,
54
+ });
55
+ return {
56
+ content: [{
57
+ type: 'text',
58
+ text: `Tool call failed.`,
59
+ }],
60
+ isError: true,
61
+ };
62
+ }
63
+ });
64
+ return {
65
+ server,
66
+ connect: transport => server.connect(transport),
67
+ close: () => server.close(),
68
+ };
69
+ }
70
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/tools/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAElE,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAA;AAG3C,OAAO,EAAgB,UAAU,EAAE,MAAM,WAAW,CAAA;AAoBpD,MAAM,UAAU,eAAe,CAC7B,MAA6B;IAE7B,MAAM,QAAQ,GAAc,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAU,CAAC,CAAC,CAAA;IAE/D,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;QACE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,mBAAmB;QACxC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,OAAO;KACnC,EACD,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAA;IAED,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAId;SACF,CAAC,CAAC;KACJ,CAAC,CAAC,CAAA;IAEH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,iBAAiB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;qBACzC,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAA;QACvD,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,wBAAwB,EAAE;gBAC7C,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;gBACzB,GAAG,EAAE,OAAO;aACb,CAAC,CAAA;YACF,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,mBAAmB;qBAC1B,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,MAAM;QACN,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;QAC/C,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;KAC5B,CAAA;AACH,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * `createHttpTransport` — Node HTTP transport for `createMcpServer`.
3
+ *
4
+ * Boots a bare `node:http` server that gates requests behind an
5
+ * optional bearer token, then hands them to the SDK's
6
+ * `StreamableHTTPServerTransport`. Runs in stateless mode
7
+ * (no `sessionIdGenerator`) — every request is self-contained, which
8
+ * matches how our tools are already wired (`handle.setContext(...)`
9
+ * carries the per-user scope, not the transport).
10
+ *
11
+ * Deliberately minimal:
12
+ * - one path (default `/mcp`)
13
+ * - one method (POST + GET both dispatched to the SDK)
14
+ * - bearer via `Authorization: Bearer <token>`, constant-time cmp
15
+ * - unauthenticated boot logs a warn but is allowed for local dev
16
+ *
17
+ * Meaningful only under Node; RN builds should never import this
18
+ * module — the guard + `sideEffects: false` keep it out of prod
19
+ * bundles.
20
+ *
21
+ * Callers wire it as:
22
+ * const t = await createHttpTransport({ port: 8787, authToken: 'x' })
23
+ * await mcpServer.connect(t.transport)
24
+ * // ...
25
+ * await t.close()
26
+ */
27
+ import type { Server as HttpServer } from 'node:http';
28
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
29
+ import type { ToolsLogger } from '../../types';
30
+ export interface CreateHttpTransportConfig {
31
+ /** Listening port. `0` picks an ephemeral port (tests). Default `0`. */
32
+ port?: number;
33
+ /** URL path. Default `/mcp`. */
34
+ path?: string;
35
+ /**
36
+ * Optional bearer token. If set, incoming requests must present
37
+ * `Authorization: Bearer <authToken>` or get a 401. If unset, all
38
+ * requests pass — logged as a warn on boot.
39
+ */
40
+ authToken?: string;
41
+ logger?: ToolsLogger;
42
+ }
43
+ export interface HttpTransportHandle {
44
+ /** The SDK transport — hand to `mcpServer.connect(...)`. */
45
+ transport: Transport;
46
+ /** The Node HTTP server — exposed for advanced callers. */
47
+ server: HttpServer;
48
+ /** Actual listening port (resolved when `port: 0`). */
49
+ port: number;
50
+ /** Shut down the HTTP server + transport. */
51
+ close: () => Promise<void>;
52
+ }
53
+ export declare function createHttpTransport(config?: CreateHttpTransportConfig): Promise<HttpTransportHandle>;
54
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../../src/tools/mcp/transports/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAmB,MAAM,IAAI,UAAU,EAAkB,MAAM,WAAW,CAAA;AAItF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,MAAM,WAAW,yBAAyB;IACxC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,SAAS,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,MAAM,EAAE,UAAU,CAAA;IAClB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,6CAA6C;IAC7C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAgCD,wBAAsB,mBAAmB,CACvC,MAAM,GAAE,yBAA8B,GACrC,OAAO,CAAC,mBAAmB,CAAC,CAkF9B"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * `createHttpTransport` — Node HTTP transport for `createMcpServer`.
3
+ *
4
+ * Boots a bare `node:http` server that gates requests behind an
5
+ * optional bearer token, then hands them to the SDK's
6
+ * `StreamableHTTPServerTransport`. Runs in stateless mode
7
+ * (no `sessionIdGenerator`) — every request is self-contained, which
8
+ * matches how our tools are already wired (`handle.setContext(...)`
9
+ * carries the per-user scope, not the transport).
10
+ *
11
+ * Deliberately minimal:
12
+ * - one path (default `/mcp`)
13
+ * - one method (POST + GET both dispatched to the SDK)
14
+ * - bearer via `Authorization: Bearer <token>`, constant-time cmp
15
+ * - unauthenticated boot logs a warn but is allowed for local dev
16
+ *
17
+ * Meaningful only under Node; RN builds should never import this
18
+ * module — the guard + `sideEffects: false` keep it out of prod
19
+ * bundles.
20
+ *
21
+ * Callers wire it as:
22
+ * const t = await createHttpTransport({ port: 8787, authToken: 'x' })
23
+ * await mcpServer.connect(t.transport)
24
+ * // ...
25
+ * await t.close()
26
+ */
27
+ import { timingSafeEqual } from 'node:crypto';
28
+ import { createServer } from 'node:http';
29
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
30
+ const UNAUTHORIZED_BODY = 'Unauthorized\n';
31
+ const NOT_FOUND_BODY = 'Not Found\n';
32
+ function bearerMatches(header, expected) {
33
+ if (!header || !header.startsWith('Bearer '))
34
+ return false;
35
+ const presented = header.slice('Bearer '.length);
36
+ const a = Buffer.from(presented);
37
+ const b = Buffer.from(expected);
38
+ if (a.length !== b.length)
39
+ return false;
40
+ return timingSafeEqual(a, b);
41
+ }
42
+ async function readBody(req) {
43
+ return new Promise((resolve, reject) => {
44
+ const chunks = [];
45
+ req.on('data', (c) => chunks.push(c));
46
+ req.on('end', () => {
47
+ if (chunks.length === 0)
48
+ return resolve(undefined);
49
+ const raw = Buffer.concat(chunks).toString('utf8');
50
+ try {
51
+ resolve(raw.length > 0 ? JSON.parse(raw) : undefined);
52
+ }
53
+ catch (err) {
54
+ reject(err instanceof Error ? err : new Error(String(err)));
55
+ }
56
+ });
57
+ req.on('error', reject);
58
+ });
59
+ }
60
+ export async function createHttpTransport(config = {}) {
61
+ const port = config.port ?? 0;
62
+ const path = config.path ?? '/mcp';
63
+ const authToken = config.authToken;
64
+ if (!authToken) {
65
+ config.logger?.warn('MCP HTTP transport started without authToken — do not expose to untrusted networks');
66
+ }
67
+ const transport = new StreamableHTTPServerTransport({
68
+ sessionIdGenerator: undefined,
69
+ });
70
+ const server = createServer((req, res) => {
71
+ // Path check — only the configured path is dispatched.
72
+ const url = req.url ?? '';
73
+ const [reqPath] = url.split('?');
74
+ if (reqPath !== path) {
75
+ res.statusCode = 404;
76
+ res.setHeader('content-type', 'text/plain');
77
+ res.end(NOT_FOUND_BODY);
78
+ return;
79
+ }
80
+ // Bearer check.
81
+ if (authToken) {
82
+ const header = req.headers.authorization;
83
+ if (!bearerMatches(header, authToken)) {
84
+ res.statusCode = 401;
85
+ res.setHeader('content-type', 'text/plain');
86
+ res.setHeader('www-authenticate', 'Bearer');
87
+ res.end(UNAUTHORIZED_BODY);
88
+ return;
89
+ }
90
+ }
91
+ // Body parse (POST) then dispatch.
92
+ void (async () => {
93
+ try {
94
+ const body = req.method === 'POST' ? await readBody(req) : undefined;
95
+ await transport.handleRequest(req, res, body);
96
+ }
97
+ catch (err) {
98
+ config.logger?.error('MCP HTTP transport request handler threw', {
99
+ err: err instanceof Error ? err.message : String(err),
100
+ });
101
+ if (!res.headersSent) {
102
+ res.statusCode = 500;
103
+ res.setHeader('content-type', 'text/plain');
104
+ res.end('Internal Server Error\n');
105
+ }
106
+ else {
107
+ res.end();
108
+ }
109
+ }
110
+ })();
111
+ });
112
+ await new Promise((resolve, reject) => {
113
+ server.once('error', reject);
114
+ server.listen(port, () => {
115
+ server.off('error', reject);
116
+ resolve();
117
+ });
118
+ });
119
+ const address = server.address();
120
+ const resolvedPort = address?.port ?? port;
121
+ return {
122
+ transport,
123
+ server,
124
+ port: resolvedPort,
125
+ close: async () => {
126
+ await new Promise((resolve) => {
127
+ server.close(() => resolve());
128
+ });
129
+ await transport.close();
130
+ },
131
+ };
132
+ }
133
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../../src/tools/mcp/transports/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `createStdioTransport` — Node stdio transport for `createMcpServer`.
3
+ *
4
+ * Reads MCP framed messages off `process.stdin` and writes them to
5
+ * `process.stdout`. Meaningful only under Node; on Hermes there is no
6
+ * stdio pipe. Callers should gate construction behind
7
+ * `shouldStartMcpServer()` so this module is never imported in prod
8
+ * RN builds (and its `node:stream` peer disappears with the rest of
9
+ * the MCP subpath under `sideEffects: false`).
10
+ *
11
+ * The SDK's `StdioServerTransport` accepts optional `stdin` / `stdout`
12
+ * streams; we expose the same knobs for tests that want to pipe
13
+ * fixtures without touching real stdio.
14
+ */
15
+ import type { Readable, Writable } from 'node:stream';
16
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
17
+ export interface CreateStdioTransportOptions {
18
+ stdin?: Readable;
19
+ stdout?: Writable;
20
+ }
21
+ export declare function createStdioTransport(options?: CreateStdioTransportOptions): Transport;
22
+ //# sourceMappingURL=stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../../src/tools/mcp/transports/stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAErD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAE9E,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAA;CAClB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC,GACxC,SAAS,CAEX"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `createStdioTransport` — Node stdio transport for `createMcpServer`.
3
+ *
4
+ * Reads MCP framed messages off `process.stdin` and writes them to
5
+ * `process.stdout`. Meaningful only under Node; on Hermes there is no
6
+ * stdio pipe. Callers should gate construction behind
7
+ * `shouldStartMcpServer()` so this module is never imported in prod
8
+ * RN builds (and its `node:stream` peer disappears with the rest of
9
+ * the MCP subpath under `sideEffects: false`).
10
+ *
11
+ * The SDK's `StdioServerTransport` accepts optional `stdin` / `stdout`
12
+ * streams; we expose the same knobs for tests that want to pipe
13
+ * fixtures without touching real stdio.
14
+ */
15
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
16
+ export function createStdioTransport(options = {}) {
17
+ return new StdioServerTransport(options.stdin, options.stdout);
18
+ }
19
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../../src/tools/mcp/transports/stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAQhF,MAAM,UAAU,oBAAoB,CAClC,UAAuC,EAAE;IAEzC,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;AAChE,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * In-memory token-bucket rate limiter for analytics tools.
3
+ *
4
+ * Three independent buckets per `(toolName, userId)`:
5
+ * - per-tool-per-minute
6
+ * - per-tool-per-hour
7
+ * - per-user-per-minute (across all tools)
8
+ *
9
+ * `check(toolName, userId)` refills every bucket by elapsed time,
10
+ * then attempts to spend one token from all three. If any lacks a
11
+ * token, returns `false` **without** spending from the others.
12
+ * Otherwise deducts one from each and returns `true`.
13
+ *
14
+ * Persistence is out of scope for v0.1.0 — process restart resets
15
+ * buckets. Audit persistence (T-09) handles the durable trail.
16
+ */
17
+ import { type RateLimitConfig } from './types';
18
+ export interface RateLimiter {
19
+ check: (toolName: string, userId: string) => boolean;
20
+ }
21
+ export interface CreateRateLimiterConfig {
22
+ config?: RateLimitConfig;
23
+ clock?: () => number;
24
+ }
25
+ export declare function createRateLimiter(cfg?: CreateRateLimiterConfig): RateLimiter;
26
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/tools/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAUlE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;CACrD;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CACrB;AAKD,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,uBAA4B,GAChC,WAAW,CA6Eb"}