@revealui/mcp 0.1.0 → 0.1.3

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 (293) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.commercial +111 -0
  3. package/README.md +3 -0
  4. package/dist/{packages/mcp/src/adapters → adapters}/db.d.ts +1 -1
  5. package/dist/adapters/db.d.ts.map +1 -0
  6. package/dist/adapters/db.js.map +1 -0
  7. package/dist/config/index.d.ts.map +1 -0
  8. package/dist/config/index.js.map +1 -0
  9. package/dist/contracts.d.ts.map +1 -0
  10. package/dist/contracts.js.map +1 -0
  11. package/dist/{packages/mcp/src/hypervisor.d.ts → hypervisor.d.ts} +56 -0
  12. package/dist/hypervisor.d.ts.map +1 -0
  13. package/dist/{packages/mcp/src/hypervisor.js → hypervisor.js} +209 -1
  14. package/dist/hypervisor.js.map +1 -0
  15. package/dist/{packages/mcp/src/index.d.ts → index.d.ts} +9 -5
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/{packages/mcp/src/index.js → index.js} +8 -4
  18. package/dist/index.js.map +1 -0
  19. package/dist/{packages/mcp/src/servers → servers}/adapter.d.ts +11 -1
  20. package/dist/servers/adapter.d.ts.map +1 -0
  21. package/dist/{packages/mcp/src/servers → servers}/adapter.js +20 -4
  22. package/dist/servers/adapter.js.map +1 -0
  23. package/dist/servers/revealui-content.d.ts +21 -0
  24. package/dist/servers/revealui-content.d.ts.map +1 -0
  25. package/dist/servers/revealui-content.js +211 -0
  26. package/dist/servers/revealui-content.js.map +1 -0
  27. package/dist/servers/revealui-email.d.ts +18 -0
  28. package/dist/servers/revealui-email.d.ts.map +1 -0
  29. package/dist/servers/revealui-email.js +190 -0
  30. package/dist/servers/revealui-email.js.map +1 -0
  31. package/dist/servers/revealui-stripe.d.ts +19 -0
  32. package/dist/servers/revealui-stripe.d.ts.map +1 -0
  33. package/dist/servers/revealui-stripe.js +228 -0
  34. package/dist/servers/revealui-stripe.js.map +1 -0
  35. package/package.json +50 -11
  36. package/.env.example +0 -9
  37. package/MCP_MAINTENANCE.md +0 -265
  38. package/__tests__/crdt.integration.test.ts +0 -156
  39. package/configs/README.md +0 -77
  40. package/configs/claude-template.json +0 -54
  41. package/dist/packages/core/src/database/ssl-config.d.ts +0 -9
  42. package/dist/packages/core/src/database/ssl-config.d.ts.map +0 -1
  43. package/dist/packages/core/src/database/ssl-config.js +0 -8
  44. package/dist/packages/core/src/database/ssl-config.js.map +0 -1
  45. package/dist/packages/core/src/features.d.ts +0 -86
  46. package/dist/packages/core/src/features.d.ts.map +0 -1
  47. package/dist/packages/core/src/features.js +0 -93
  48. package/dist/packages/core/src/features.js.map +0 -1
  49. package/dist/packages/core/src/license.d.ts +0 -75
  50. package/dist/packages/core/src/license.d.ts.map +0 -1
  51. package/dist/packages/core/src/license.js +0 -174
  52. package/dist/packages/core/src/license.js.map +0 -1
  53. package/dist/packages/core/src/monitoring/alerts.d.ts +0 -118
  54. package/dist/packages/core/src/monitoring/alerts.d.ts.map +0 -1
  55. package/dist/packages/core/src/monitoring/alerts.js +0 -325
  56. package/dist/packages/core/src/monitoring/alerts.js.map +0 -1
  57. package/dist/packages/core/src/monitoring/cleanup-manager.d.ts +0 -71
  58. package/dist/packages/core/src/monitoring/cleanup-manager.d.ts.map +0 -1
  59. package/dist/packages/core/src/monitoring/cleanup-manager.js +0 -227
  60. package/dist/packages/core/src/monitoring/cleanup-manager.js.map +0 -1
  61. package/dist/packages/core/src/monitoring/health-monitor.d.ts +0 -22
  62. package/dist/packages/core/src/monitoring/health-monitor.d.ts.map +0 -1
  63. package/dist/packages/core/src/monitoring/health-monitor.js +0 -143
  64. package/dist/packages/core/src/monitoring/health-monitor.js.map +0 -1
  65. package/dist/packages/core/src/monitoring/index.d.ts +0 -14
  66. package/dist/packages/core/src/monitoring/index.d.ts.map +0 -1
  67. package/dist/packages/core/src/monitoring/index.js +0 -18
  68. package/dist/packages/core/src/monitoring/index.js.map +0 -1
  69. package/dist/packages/core/src/monitoring/process-registry.d.ts +0 -97
  70. package/dist/packages/core/src/monitoring/process-registry.d.ts.map +0 -1
  71. package/dist/packages/core/src/monitoring/process-registry.js +0 -223
  72. package/dist/packages/core/src/monitoring/process-registry.js.map +0 -1
  73. package/dist/packages/core/src/monitoring/types.d.ts +0 -231
  74. package/dist/packages/core/src/monitoring/types.d.ts.map +0 -1
  75. package/dist/packages/core/src/monitoring/types.js +0 -43
  76. package/dist/packages/core/src/monitoring/types.js.map +0 -1
  77. package/dist/packages/core/src/monitoring/zombie-detector.d.ts +0 -81
  78. package/dist/packages/core/src/monitoring/zombie-detector.d.ts.map +0 -1
  79. package/dist/packages/core/src/monitoring/zombie-detector.js +0 -232
  80. package/dist/packages/core/src/monitoring/zombie-detector.js.map +0 -1
  81. package/dist/packages/core/src/observability/logger.d.ts +0 -47
  82. package/dist/packages/core/src/observability/logger.d.ts.map +0 -1
  83. package/dist/packages/core/src/observability/logger.js +0 -141
  84. package/dist/packages/core/src/observability/logger.js.map +0 -1
  85. package/dist/packages/core/src/utils/logger-server.d.ts +0 -32
  86. package/dist/packages/core/src/utils/logger-server.d.ts.map +0 -1
  87. package/dist/packages/core/src/utils/logger-server.js +0 -69
  88. package/dist/packages/core/src/utils/logger-server.js.map +0 -1
  89. package/dist/packages/core/src/utils/request-context.d.ts +0 -143
  90. package/dist/packages/core/src/utils/request-context.d.ts.map +0 -1
  91. package/dist/packages/core/src/utils/request-context.js +0 -169
  92. package/dist/packages/core/src/utils/request-context.js.map +0 -1
  93. package/dist/packages/dev/src/code-validator/index.d.ts +0 -20
  94. package/dist/packages/dev/src/code-validator/index.d.ts.map +0 -1
  95. package/dist/packages/dev/src/code-validator/index.js +0 -20
  96. package/dist/packages/dev/src/code-validator/index.js.map +0 -1
  97. package/dist/packages/dev/src/code-validator/types.d.ts +0 -67
  98. package/dist/packages/dev/src/code-validator/types.d.ts.map +0 -1
  99. package/dist/packages/dev/src/code-validator/types.js +0 -7
  100. package/dist/packages/dev/src/code-validator/types.js.map +0 -1
  101. package/dist/packages/dev/src/code-validator/validator.d.ts +0 -48
  102. package/dist/packages/dev/src/code-validator/validator.d.ts.map +0 -1
  103. package/dist/packages/dev/src/code-validator/validator.js +0 -176
  104. package/dist/packages/dev/src/code-validator/validator.js.map +0 -1
  105. package/dist/packages/mcp/src/adapters/db.d.ts.map +0 -1
  106. package/dist/packages/mcp/src/adapters/db.js.map +0 -1
  107. package/dist/packages/mcp/src/config/index.d.ts.map +0 -1
  108. package/dist/packages/mcp/src/config/index.js.map +0 -1
  109. package/dist/packages/mcp/src/contracts.d.ts.map +0 -1
  110. package/dist/packages/mcp/src/contracts.js.map +0 -1
  111. package/dist/packages/mcp/src/hypervisor.d.ts.map +0 -1
  112. package/dist/packages/mcp/src/hypervisor.js.map +0 -1
  113. package/dist/packages/mcp/src/index.d.ts.map +0 -1
  114. package/dist/packages/mcp/src/index.js.map +0 -1
  115. package/dist/packages/mcp/src/servers/adapter.d.ts.map +0 -1
  116. package/dist/packages/mcp/src/servers/adapter.js.map +0 -1
  117. package/dist/packages/mcp/src/servers/code-validator.d.ts +0 -24
  118. package/dist/packages/mcp/src/servers/code-validator.d.ts.map +0 -1
  119. package/dist/packages/mcp/src/servers/code-validator.js +0 -156
  120. package/dist/packages/mcp/src/servers/code-validator.js.map +0 -1
  121. package/dist/packages/mcp/src/servers/neon.d.ts +0 -11
  122. package/dist/packages/mcp/src/servers/neon.d.ts.map +0 -1
  123. package/dist/packages/mcp/src/servers/neon.js +0 -90
  124. package/dist/packages/mcp/src/servers/neon.js.map +0 -1
  125. package/dist/packages/mcp/src/servers/next-devtools.d.ts +0 -11
  126. package/dist/packages/mcp/src/servers/next-devtools.d.ts.map +0 -1
  127. package/dist/packages/mcp/src/servers/next-devtools.js +0 -215
  128. package/dist/packages/mcp/src/servers/next-devtools.js.map +0 -1
  129. package/dist/packages/mcp/src/servers/playwright.d.ts +0 -11
  130. package/dist/packages/mcp/src/servers/playwright.d.ts.map +0 -1
  131. package/dist/packages/mcp/src/servers/playwright.js +0 -68
  132. package/dist/packages/mcp/src/servers/playwright.js.map +0 -1
  133. package/dist/packages/mcp/src/servers/stripe.d.ts +0 -11
  134. package/dist/packages/mcp/src/servers/stripe.d.ts.map +0 -1
  135. package/dist/packages/mcp/src/servers/stripe.js +0 -86
  136. package/dist/packages/mcp/src/servers/stripe.js.map +0 -1
  137. package/dist/packages/mcp/src/servers/supabase.d.ts +0 -11
  138. package/dist/packages/mcp/src/servers/supabase.d.ts.map +0 -1
  139. package/dist/packages/mcp/src/servers/supabase.js +0 -144
  140. package/dist/packages/mcp/src/servers/supabase.js.map +0 -1
  141. package/dist/packages/mcp/src/servers/vercel.d.ts +0 -11
  142. package/dist/packages/mcp/src/servers/vercel.d.ts.map +0 -1
  143. package/dist/packages/mcp/src/servers/vercel.js +0 -87
  144. package/dist/packages/mcp/src/servers/vercel.js.map +0 -1
  145. package/dist/packages/mcp/src/servers/vultr-test.d.ts +0 -3
  146. package/dist/packages/mcp/src/servers/vultr-test.d.ts.map +0 -1
  147. package/dist/packages/mcp/src/servers/vultr-test.js +0 -82
  148. package/dist/packages/mcp/src/servers/vultr-test.js.map +0 -1
  149. package/dist/scripts/lib/analyzers/console-analyzer.d.ts +0 -188
  150. package/dist/scripts/lib/analyzers/console-analyzer.d.ts.map +0 -1
  151. package/dist/scripts/lib/analyzers/console-analyzer.js +0 -432
  152. package/dist/scripts/lib/analyzers/console-analyzer.js.map +0 -1
  153. package/dist/scripts/lib/analyzers/index.d.ts +0 -11
  154. package/dist/scripts/lib/analyzers/index.d.ts.map +0 -1
  155. package/dist/scripts/lib/analyzers/index.js +0 -11
  156. package/dist/scripts/lib/analyzers/index.js.map +0 -1
  157. package/dist/scripts/lib/args.d.ts +0 -104
  158. package/dist/scripts/lib/args.d.ts.map +0 -1
  159. package/dist/scripts/lib/args.js +0 -304
  160. package/dist/scripts/lib/args.js.map +0 -1
  161. package/dist/scripts/lib/cache.d.ts +0 -185
  162. package/dist/scripts/lib/cache.d.ts.map +0 -1
  163. package/dist/scripts/lib/cache.js +0 -390
  164. package/dist/scripts/lib/cache.js.map +0 -1
  165. package/dist/scripts/lib/cli/dispatch.d.ts +0 -116
  166. package/dist/scripts/lib/cli/dispatch.d.ts.map +0 -1
  167. package/dist/scripts/lib/cli/dispatch.js +0 -206
  168. package/dist/scripts/lib/cli/dispatch.js.map +0 -1
  169. package/dist/scripts/lib/cli/index.d.ts +0 -10
  170. package/dist/scripts/lib/cli/index.d.ts.map +0 -1
  171. package/dist/scripts/lib/cli/index.js +0 -10
  172. package/dist/scripts/lib/cli/index.js.map +0 -1
  173. package/dist/scripts/lib/database/ssl-config.d.ts +0 -26
  174. package/dist/scripts/lib/database/ssl-config.d.ts.map +0 -1
  175. package/dist/scripts/lib/database/ssl-config.js +0 -47
  176. package/dist/scripts/lib/database/ssl-config.js.map +0 -1
  177. package/dist/scripts/lib/errors.d.ts +0 -218
  178. package/dist/scripts/lib/errors.d.ts.map +0 -1
  179. package/dist/scripts/lib/errors.js +0 -543
  180. package/dist/scripts/lib/errors.js.map +0 -1
  181. package/dist/scripts/lib/exec.d.ts +0 -107
  182. package/dist/scripts/lib/exec.d.ts.map +0 -1
  183. package/dist/scripts/lib/exec.js +0 -232
  184. package/dist/scripts/lib/exec.js.map +0 -1
  185. package/dist/scripts/lib/index.d.ts +0 -50
  186. package/dist/scripts/lib/index.d.ts.map +0 -1
  187. package/dist/scripts/lib/index.js +0 -65
  188. package/dist/scripts/lib/index.js.map +0 -1
  189. package/dist/scripts/lib/logger.d.ts +0 -50
  190. package/dist/scripts/lib/logger.d.ts.map +0 -1
  191. package/dist/scripts/lib/logger.js +0 -159
  192. package/dist/scripts/lib/logger.js.map +0 -1
  193. package/dist/scripts/lib/output.d.ts +0 -149
  194. package/dist/scripts/lib/output.d.ts.map +0 -1
  195. package/dist/scripts/lib/output.js +0 -263
  196. package/dist/scripts/lib/output.js.map +0 -1
  197. package/dist/scripts/lib/parallel.d.ts +0 -164
  198. package/dist/scripts/lib/parallel.d.ts.map +0 -1
  199. package/dist/scripts/lib/parallel.js +0 -355
  200. package/dist/scripts/lib/parallel.js.map +0 -1
  201. package/dist/scripts/lib/paths.d.ts +0 -92
  202. package/dist/scripts/lib/paths.d.ts.map +0 -1
  203. package/dist/scripts/lib/paths.js +0 -171
  204. package/dist/scripts/lib/paths.js.map +0 -1
  205. package/dist/scripts/lib/state/adapters/memory.d.ts +0 -42
  206. package/dist/scripts/lib/state/adapters/memory.d.ts.map +0 -1
  207. package/dist/scripts/lib/state/adapters/memory.js +0 -110
  208. package/dist/scripts/lib/state/adapters/memory.js.map +0 -1
  209. package/dist/scripts/lib/state/adapters/pglite.d.ts +0 -46
  210. package/dist/scripts/lib/state/adapters/pglite.d.ts.map +0 -1
  211. package/dist/scripts/lib/state/adapters/pglite.js +0 -256
  212. package/dist/scripts/lib/state/adapters/pglite.js.map +0 -1
  213. package/dist/scripts/lib/state/index.d.ts +0 -16
  214. package/dist/scripts/lib/state/index.d.ts.map +0 -1
  215. package/dist/scripts/lib/state/index.js +0 -16
  216. package/dist/scripts/lib/state/index.js.map +0 -1
  217. package/dist/scripts/lib/state/types.d.ts +0 -111
  218. package/dist/scripts/lib/state/types.d.ts.map +0 -1
  219. package/dist/scripts/lib/state/types.js +0 -8
  220. package/dist/scripts/lib/state/types.js.map +0 -1
  221. package/dist/scripts/lib/state/workflow-state.d.ts +0 -110
  222. package/dist/scripts/lib/state/workflow-state.d.ts.map +0 -1
  223. package/dist/scripts/lib/state/workflow-state.js +0 -331
  224. package/dist/scripts/lib/state/workflow-state.js.map +0 -1
  225. package/dist/scripts/lib/telemetry.d.ts +0 -194
  226. package/dist/scripts/lib/telemetry.d.ts.map +0 -1
  227. package/dist/scripts/lib/telemetry.js +0 -394
  228. package/dist/scripts/lib/telemetry.js.map +0 -1
  229. package/dist/scripts/lib/utils.d.ts +0 -270
  230. package/dist/scripts/lib/utils.d.ts.map +0 -1
  231. package/dist/scripts/lib/utils.js +0 -473
  232. package/dist/scripts/lib/utils.js.map +0 -1
  233. package/dist/scripts/lib/validation/database.d.ts +0 -83
  234. package/dist/scripts/lib/validation/database.d.ts.map +0 -1
  235. package/dist/scripts/lib/validation/database.js +0 -199
  236. package/dist/scripts/lib/validation/database.js.map +0 -1
  237. package/dist/scripts/lib/validation/env.d.ts +0 -80
  238. package/dist/scripts/lib/validation/env.d.ts.map +0 -1
  239. package/dist/scripts/lib/validation/env.js +0 -246
  240. package/dist/scripts/lib/validation/env.js.map +0 -1
  241. package/dist/scripts/lib/validation/index.d.ts +0 -16
  242. package/dist/scripts/lib/validation/index.d.ts.map +0 -1
  243. package/dist/scripts/lib/validation/index.js +0 -16
  244. package/dist/scripts/lib/validation/index.js.map +0 -1
  245. package/dist/scripts/lib/validation/post-execution.d.ts +0 -74
  246. package/dist/scripts/lib/validation/post-execution.d.ts.map +0 -1
  247. package/dist/scripts/lib/validation/post-execution.js +0 -110
  248. package/dist/scripts/lib/validation/post-execution.js.map +0 -1
  249. package/dist/scripts/lib/validation/pre-execution.d.ts +0 -165
  250. package/dist/scripts/lib/validation/pre-execution.d.ts.map +0 -1
  251. package/dist/scripts/lib/validation/pre-execution.js +0 -466
  252. package/dist/scripts/lib/validation/pre-execution.js.map +0 -1
  253. package/dist/scripts/lib/validators/documentation-validator.d.ts +0 -242
  254. package/dist/scripts/lib/validators/documentation-validator.d.ts.map +0 -1
  255. package/dist/scripts/lib/validators/documentation-validator.js +0 -584
  256. package/dist/scripts/lib/validators/documentation-validator.js.map +0 -1
  257. package/dist/scripts/lib/validators/index.d.ts +0 -11
  258. package/dist/scripts/lib/validators/index.d.ts.map +0 -1
  259. package/dist/scripts/lib/validators/index.js +0 -11
  260. package/dist/scripts/lib/validators/index.js.map +0 -1
  261. package/docker-compose.yml +0 -46
  262. package/docs/INDEX.md +0 -88
  263. package/docs/README.md +0 -774
  264. package/docs/SETUP.md +0 -264
  265. package/docs/servers/code-validator.md +0 -586
  266. package/eslint.config.js +0 -7
  267. package/migrations/0001_add_crdt_columns.sql +0 -8
  268. package/migrations/0001_rollback.sql +0 -6
  269. package/migrations/005_performance_indexes.sql +0 -190
  270. package/migrations/backfill_crdt_meta.js +0 -45
  271. package/src/__tests__/hypervisor.test.ts +0 -212
  272. package/src/adapters/db.ts +0 -180
  273. package/src/config/config.json +0 -49
  274. package/src/config/index.ts +0 -30
  275. package/src/contracts.ts +0 -221
  276. package/src/hypervisor.ts +0 -464
  277. package/src/index.ts +0 -87
  278. package/src/servers/adapter.ts +0 -643
  279. package/src/servers/code-validator.ts +0 -188
  280. package/src/servers/neon.ts +0 -103
  281. package/src/servers/next-devtools.ts +0 -230
  282. package/src/servers/playwright.ts +0 -77
  283. package/src/servers/stripe.ts +0 -99
  284. package/src/servers/supabase.ts +0 -161
  285. package/src/servers/vercel.ts +0 -100
  286. package/src/servers/vultr-test.ts +0 -97
  287. package/tsconfig.json +0 -12
  288. package/vitest.config.ts +0 -22
  289. /package/dist/{packages/mcp/src/adapters → adapters}/db.js +0 -0
  290. /package/dist/{packages/mcp/src/config → config}/index.d.ts +0 -0
  291. /package/dist/{packages/mcp/src/config → config}/index.js +0 -0
  292. /package/dist/{packages/mcp/src/contracts.d.ts → contracts.d.ts} +0 -0
  293. /package/dist/{packages/mcp/src/contracts.js → contracts.js} +0 -0
@@ -1,30 +0,0 @@
1
- export type McpMetricsMode = 'logs' | 'otel' | 'prometheus'
2
-
3
- export interface McpConfig {
4
- persistenceDriver: 'pglite' | 'postgres'
5
- electricDatabaseUrl: string | null
6
- electricApiKey: string | null
7
- metricsMode: McpMetricsMode
8
- pgvectorEnabled: boolean
9
- }
10
-
11
- function boolFromEnv(v: string | undefined, fallback = false) {
12
- if (v === undefined) return fallback
13
- return ['1', 'true', 'yes'].includes(v.toLowerCase())
14
- }
15
-
16
- export function getMcpConfig(): McpConfig {
17
- const persistenceDriver =
18
- (process.env.MCP_PERSISTENCE_DRIVER as 'pglite' | 'postgres') || 'pglite'
19
- const metricsMode = (process.env.MCP_METRICS_MODE as McpMetricsMode) || 'logs'
20
-
21
- return {
22
- persistenceDriver,
23
- electricDatabaseUrl: process.env.ELECTRIC_DATABASE_URL || null,
24
- electricApiKey: process.env.ELECTRIC_API_KEY || null,
25
- metricsMode,
26
- pgvectorEnabled: boolFromEnv(process.env.PGVECTOR_ENABLED, false),
27
- }
28
- }
29
-
30
- export default getMcpConfig
package/src/contracts.ts DELETED
@@ -1,221 +0,0 @@
1
- /**
2
- * MCP Contracts
3
- *
4
- * Zod schemas for MCP-specific types, built on top of @revealui/contracts.
5
- * These provide runtime validation for MCP request/response payloads
6
- * and bridge MCP SDK tool definitions to contracts ToolDefinition.
7
- */
8
-
9
- import {
10
- type A2AAgentCard,
11
- type A2AAuth,
12
- type AgentDefinition,
13
- agentDefinitionToCard,
14
- type ToolDefinition,
15
- ToolDefinitionSchema,
16
- type ToolParameter,
17
- z,
18
- } from '@revealui/contracts'
19
-
20
- // =============================================================================
21
- // MCP Request / Response Schemas
22
- // =============================================================================
23
-
24
- /**
25
- * Schema for MCP request options (idempotency, retry, dry-run)
26
- */
27
- export const MCPRequestOptionsSchema = z.object({
28
- timeout: z.number().positive().optional(),
29
- retries: z.number().int().nonnegative().optional(),
30
- dryRun: z.boolean().optional(),
31
- idempotencyKey: z.string().optional(),
32
- idempotencyTTL: z.number().positive().optional(),
33
- })
34
-
35
- export type MCPRequestOptions = z.infer<typeof MCPRequestOptionsSchema>
36
-
37
- /**
38
- * Schema for an MCP request payload
39
- */
40
- export const MCPRequestSchema = z.object({
41
- action: z.string().min(1),
42
- parameters: z.record(z.string(), z.unknown()).optional(),
43
- options: MCPRequestOptionsSchema.optional(),
44
- })
45
-
46
- export type MCPRequest = z.infer<typeof MCPRequestSchema>
47
-
48
- /**
49
- * Schema for MCP response metadata
50
- */
51
- export const MCPResponseMetadataSchema = z.object({
52
- duration: z.number().nonnegative(),
53
- retries: z.number().int().nonnegative(),
54
- service: z.string(),
55
- cached: z.boolean().optional(),
56
- idempotencyKey: z.string().optional(),
57
- })
58
-
59
- export type MCPResponseMetadata = z.infer<typeof MCPResponseMetadataSchema>
60
-
61
- /**
62
- * Schema for an MCP response payload
63
- */
64
- export const MCPResponseSchema = z.object({
65
- success: z.boolean(),
66
- data: z.unknown().optional(),
67
- error: z.string().optional(),
68
- metadata: MCPResponseMetadataSchema.optional(),
69
- })
70
-
71
- export type MCPResponse = z.infer<typeof MCPResponseSchema>
72
-
73
- /**
74
- * Schema for MCP adapter configuration
75
- */
76
- export const MCPAdapterConfigSchema = z.object({
77
- apiKey: z.string().optional(),
78
- baseUrl: z.string().url().optional(),
79
- timeout: z.number().positive().optional(),
80
- retries: z.number().int().nonnegative().optional(),
81
- environment: z.enum(['development', 'production']).optional(),
82
- })
83
-
84
- export type MCPAdapterConfig = z.infer<typeof MCPAdapterConfigSchema>
85
-
86
- // =============================================================================
87
- // Tool Definition Bridge
88
- // =============================================================================
89
-
90
- /**
91
- * Converts an MCP SDK tool definition (JSON Schema-based) to a contracts ToolDefinition.
92
- *
93
- * The MCP SDK uses JSON Schema for tool `inputSchema`, while contracts uses
94
- * a structured ToolParameter format. This bridge maps between them.
95
- */
96
- export function mcpToolToContractsToolDefinition(mcpTool: {
97
- name: string
98
- description?: string
99
- inputSchema?: {
100
- type: string
101
- properties?: Record<
102
- string,
103
- { type?: string; description?: string; default?: unknown; enum?: string[] }
104
- >
105
- required?: string[]
106
- }
107
- }): ToolDefinition {
108
- const parameters: Record<string, ToolParameter> = {}
109
-
110
- if (mcpTool.inputSchema?.properties) {
111
- const required = new Set(mcpTool.inputSchema.required ?? [])
112
-
113
- for (const [key, prop] of Object.entries(mcpTool.inputSchema.properties)) {
114
- parameters[key] = {
115
- type: (prop.type as ToolParameter['type']) ?? 'string',
116
- description: prop.description ?? '',
117
- required: required.has(key),
118
- ...(prop.default !== undefined && { default: prop.default }),
119
- ...(prop.enum && { enum: prop.enum }),
120
- }
121
- }
122
- }
123
-
124
- return ToolDefinitionSchema.parse({
125
- name: mcpTool.name,
126
- description: mcpTool.description ?? `MCP tool: ${mcpTool.name}`,
127
- parameters,
128
- destructive: false,
129
- })
130
- }
131
-
132
- /**
133
- * Converts a contracts ToolDefinition back to an MCP SDK-compatible tool shape.
134
- * Useful for registering contracts-defined tools with MCP servers.
135
- */
136
- export function contractsToolDefinitionToMcpTool(tool: ToolDefinition): {
137
- name: string
138
- description: string
139
- inputSchema: {
140
- type: 'object'
141
- properties: Record<
142
- string,
143
- { type: string; description: string; default?: unknown; enum?: string[] }
144
- >
145
- required: string[]
146
- }
147
- } {
148
- const properties: Record<
149
- string,
150
- { type: string; description: string; default?: unknown; enum?: string[] }
151
- > = {}
152
- const required: string[] = []
153
-
154
- for (const [key, param] of Object.entries(tool.parameters)) {
155
- properties[key] = {
156
- type: param.type,
157
- description: param.description,
158
- ...(param.default !== undefined && { default: param.default }),
159
- ...(param.enum && { enum: param.enum }),
160
- }
161
-
162
- if (param.required) {
163
- required.push(key)
164
- }
165
- }
166
-
167
- return {
168
- name: tool.name,
169
- description: tool.description,
170
- inputSchema: {
171
- type: 'object',
172
- properties,
173
- required,
174
- },
175
- }
176
- }
177
-
178
- // =============================================================================
179
- // Agent Card Bridge
180
- // =============================================================================
181
-
182
- /**
183
- * Converts a RevealUI AgentDefinition to a Google A2A AgentCard.
184
- * Wraps the contracts-level `agentDefinitionToCard` with optional MCP-specific overrides.
185
- *
186
- * @param agent - The agent definition (source of truth)
187
- * @param baseUrl - The server base URL (e.g. https://api.revealui.com)
188
- * @param opts - Optional overrides for auth scheme and streaming capability
189
- */
190
- export function agentDefinitionToAgentCard(
191
- agent: AgentDefinition,
192
- baseUrl: string,
193
- opts?: { authScheme?: A2AAuth; streaming?: boolean },
194
- ): A2AAgentCard {
195
- const card = agentDefinitionToCard(agent, baseUrl)
196
- if (!opts) return card
197
-
198
- const { authScheme, streaming } = opts
199
- return {
200
- ...card,
201
- ...(authScheme !== undefined && { authentication: authScheme }),
202
- capabilities: {
203
- ...(card.capabilities ?? {
204
- streaming: false,
205
- pushNotifications: false,
206
- stateTransitionHistory: false,
207
- }),
208
- streaming: streaming ?? card.capabilities?.streaming ?? false,
209
- },
210
- }
211
- }
212
-
213
- /**
214
- * Converts all tools in a RevealUI AgentDefinition to MCP tool specs.
215
- * Uses `contractsToolDefinitionToMcpTool` for each tool.
216
- */
217
- export function agentDefinitionToMcpTools(
218
- agent: AgentDefinition,
219
- ): ReturnType<typeof contractsToolDefinitionToMcpTool>[] {
220
- return agent.tools.map(contractsToolDefinitionToMcpTool)
221
- }
package/src/hypervisor.ts DELETED
@@ -1,464 +0,0 @@
1
- /**
2
- * MCP Hypervisor
3
- *
4
- * Manages N running MCP server processes, pings them for liveness, and
5
- * dynamically exposes their tools at runtime. Inspired by the
6
- * MCPCompatibilityLayer/MCPHypervisor pattern from AnythingLLM.
7
- *
8
- * Architecture:
9
- * - Singleton: one hypervisor per process manages all MCP servers
10
- * - Each server is spawned with piped stdio for JSON-RPC communication
11
- * - Tool names are namespaced: @@mcp_{serverName}_{toolName}
12
- * - Health check loop: every 60s, process.exitCode check + tools/list probe
13
- *
14
- * Wire format: newline-delimited JSON-RPC 2.0 (stdin/stdout)
15
- */
16
-
17
- import { type ChildProcess, spawn } from 'node:child_process'
18
- import { registerCleanupHandler } from '@revealui/core/monitoring'
19
- import { logger } from '@revealui/core/observability/logger'
20
-
21
- // =============================================================================
22
- // Types
23
- // =============================================================================
24
-
25
- export interface MCPServerConfig {
26
- /** Unique name for this server (used in tool namespacing) */
27
- name: string
28
- /** Executable to run (e.g. 'node', 'pnpm') */
29
- command: string
30
- /** Arguments to the command */
31
- args: string[]
32
- /** Additional environment variables */
33
- env?: Record<string, string>
34
- }
35
-
36
- export interface MCPTool {
37
- name: string
38
- description: string
39
- inputSchema: {
40
- type: 'object'
41
- properties?: Record<string, unknown>
42
- required?: string[]
43
- }
44
- }
45
-
46
- export interface NamespacedTool {
47
- /** Namespaced name: @@mcp_{serverName}_{toolName} */
48
- namespacedName: string
49
- serverName: string
50
- tool: MCPTool
51
- }
52
-
53
- interface ServerEntry {
54
- config: MCPServerConfig
55
- process: ChildProcess | null
56
- tools: MCPTool[]
57
- healthy: boolean
58
- lastPingAt: number | null
59
- }
60
-
61
- interface JsonRpcRequest {
62
- jsonrpc: '2.0'
63
- id: number
64
- method: string
65
- params?: unknown
66
- }
67
-
68
- interface JsonRpcResponse {
69
- jsonrpc: '2.0'
70
- id: number
71
- result?: unknown
72
- error?: { code: number; message: string }
73
- }
74
-
75
- // =============================================================================
76
- // Constants
77
- // =============================================================================
78
-
79
- const HEALTH_CHECK_INTERVAL_MS = 60_000
80
- const REQUEST_TIMEOUT_MS = 5_000
81
- const MCP_TOOL_PREFIX = '@@mcp'
82
-
83
- // =============================================================================
84
- // MCPHypervisor
85
- // =============================================================================
86
-
87
- /**
88
- * Singleton that manages MCP server processes and their tool registries.
89
- *
90
- * @example
91
- * ```typescript
92
- * const hypervisor = MCPHypervisor.getInstance()
93
- *
94
- * hypervisor.registerServer({
95
- * name: 'stripe',
96
- * command: 'pnpm',
97
- * args: ['dlx', '@stripe/mcp', '--tools=all', '--api-key=sk_...'],
98
- * })
99
- *
100
- * await hypervisor.startServer('stripe')
101
- * const tools = hypervisor.getAllTools()
102
- * // tools[0].namespacedName === '@@mcp_stripe_create_payment_intent'
103
- * ```
104
- */
105
- export class MCPHypervisor {
106
- private static instance: MCPHypervisor | null = null
107
-
108
- private servers: Map<string, ServerEntry> = new Map()
109
- private requestCounter = 0
110
- private pendingRequests: Map<
111
- number,
112
- { resolve: (value: unknown) => void; reject: (error: Error) => void; timer: NodeJS.Timeout }
113
- > = new Map()
114
- private healthCheckTimer: NodeJS.Timeout | null = null
115
-
116
- private constructor() {
117
- registerCleanupHandler(
118
- 'mcp-hypervisor',
119
- async () => this.stopAll(),
120
- 'Stop all MCP server processes',
121
- 85,
122
- )
123
- this.startHealthCheckLoop()
124
- }
125
-
126
- static getInstance(): MCPHypervisor {
127
- if (!MCPHypervisor.instance) {
128
- MCPHypervisor.instance = new MCPHypervisor()
129
- }
130
- return MCPHypervisor.instance
131
- }
132
-
133
- // ---------------------------------------------------------------------------
134
- // Server registration
135
- // ---------------------------------------------------------------------------
136
-
137
- /**
138
- * Register an MCP server configuration without starting it.
139
- */
140
- registerServer(config: MCPServerConfig): void {
141
- if (this.servers.has(config.name)) {
142
- logger.warn(`[MCPHypervisor] Server "${config.name}" is already registered`)
143
- return
144
- }
145
- this.servers.set(config.name, {
146
- config,
147
- process: null,
148
- tools: [],
149
- healthy: false,
150
- lastPingAt: null,
151
- })
152
- logger.info(`[MCPHypervisor] Registered server: ${config.name}`)
153
- }
154
-
155
- /**
156
- * Unregister a server (stops it first if running).
157
- */
158
- async unregisterServer(name: string): Promise<void> {
159
- const entry = this.servers.get(name)
160
- if (!entry) return
161
- if (entry.process) await this.stopServer(name)
162
- this.servers.delete(name)
163
- }
164
-
165
- // ---------------------------------------------------------------------------
166
- // Lifecycle
167
- // ---------------------------------------------------------------------------
168
-
169
- /**
170
- * Spawn the MCP server process with piped stdio.
171
- * Tools are discovered via `listServerTools()` after startup.
172
- */
173
- async startServer(name: string): Promise<void> {
174
- const entry = this.servers.get(name)
175
- if (!entry) throw new Error(`[MCPHypervisor] Unknown server: "${name}"`)
176
- if (entry.process && entry.process.exitCode === null) {
177
- logger.info(`[MCPHypervisor] Server "${name}" is already running`)
178
- return
179
- }
180
-
181
- const { config } = entry
182
- const child = spawn(config.command, config.args, {
183
- stdio: ['pipe', 'pipe', 'pipe'],
184
- env: { ...process.env, ...config.env },
185
- })
186
-
187
- entry.process = child
188
- entry.healthy = false
189
- entry.tools = []
190
-
191
- // Buffer incoming stdout for JSON-RPC response parsing
192
- let buffer = ''
193
- child.stdout?.on('data', (chunk: Buffer) => {
194
- buffer += chunk.toString()
195
- const lines = buffer.split('\n')
196
- buffer = lines.pop() ?? '' // keep incomplete line in buffer
197
- for (const line of lines) {
198
- const trimmed = line.trim()
199
- if (!trimmed) continue
200
- try {
201
- const msg = JSON.parse(trimmed) as JsonRpcResponse
202
- this.handleResponse(msg)
203
- } catch {
204
- // Non-JSON output from server — ignore
205
- }
206
- }
207
- })
208
-
209
- child.stderr?.on('data', (chunk: Buffer) => {
210
- logger.warn(`[MCPHypervisor] ${name} stderr: ${chunk.toString().trim()}`)
211
- })
212
-
213
- child.on('exit', (code) => {
214
- logger.warn(`[MCPHypervisor] Server "${name}" exited with code ${code}`)
215
- entry.healthy = false
216
- // Reject all pending requests for this server
217
- for (const [id, pending] of this.pendingRequests) {
218
- pending.reject(new Error(`Server "${name}" exited`))
219
- clearTimeout(pending.timer)
220
- this.pendingRequests.delete(id)
221
- }
222
- })
223
-
224
- // Allow a brief startup window, then probe tools
225
- await new Promise<void>((resolve) => setTimeout(resolve, 500))
226
-
227
- try {
228
- await this.listServerTools(name)
229
- entry.healthy = true
230
- logger.info(`[MCPHypervisor] Server "${name}" started (${entry.tools.length} tools)`)
231
- } catch (error) {
232
- logger.warn(
233
- `[MCPHypervisor] Server "${name}" started but tool discovery failed: ${
234
- error instanceof Error ? error.message : String(error)
235
- }`,
236
- )
237
- // Still mark healthy if the process is alive (tools may not be supported)
238
- entry.healthy = entry.process.exitCode === null
239
- }
240
- }
241
-
242
- /**
243
- * Stop a running MCP server process.
244
- */
245
- async stopServer(name: string): Promise<void> {
246
- const entry = this.servers.get(name)
247
- if (!entry?.process) return
248
-
249
- entry.process.kill('SIGTERM')
250
- await new Promise<void>((resolve) => setTimeout(resolve, 200))
251
-
252
- if (entry.process.exitCode === null) {
253
- entry.process.kill('SIGKILL')
254
- }
255
-
256
- entry.process = null
257
- entry.healthy = false
258
- entry.tools = []
259
- logger.info(`[MCPHypervisor] Stopped server: ${name}`)
260
- }
261
-
262
- /**
263
- * Stop all running servers.
264
- */
265
- async stopAll(): Promise<void> {
266
- this.stopHealthCheckLoop()
267
- await Promise.all(Array.from(this.servers.keys()).map((name) => this.stopServer(name)))
268
- }
269
-
270
- // ---------------------------------------------------------------------------
271
- // JSON-RPC communication
272
- // ---------------------------------------------------------------------------
273
-
274
- /**
275
- * Send a JSON-RPC request to a running server and await the response.
276
- */
277
- private sendRequest(name: string, method: string, params?: unknown): Promise<unknown> {
278
- const entry = this.servers.get(name)
279
- if (!entry?.process || entry.process.exitCode !== null) {
280
- return Promise.reject(new Error(`Server "${name}" is not running`))
281
- }
282
-
283
- const id = ++this.requestCounter
284
- const request: JsonRpcRequest = {
285
- jsonrpc: '2.0',
286
- id,
287
- method,
288
- ...(params !== undefined && { params }),
289
- }
290
-
291
- return new Promise((resolve, reject) => {
292
- const timer = setTimeout(() => {
293
- this.pendingRequests.delete(id)
294
- reject(new Error(`Request ${method} timed out after ${REQUEST_TIMEOUT_MS}ms`))
295
- }, REQUEST_TIMEOUT_MS)
296
-
297
- this.pendingRequests.set(id, { resolve, reject, timer })
298
-
299
- try {
300
- entry.process?.stdin?.write(`${JSON.stringify(request)}\n`)
301
- } catch (error) {
302
- clearTimeout(timer)
303
- this.pendingRequests.delete(id)
304
- reject(error)
305
- }
306
- })
307
- }
308
-
309
- private handleResponse(msg: JsonRpcResponse): void {
310
- const pending = this.pendingRequests.get(msg.id)
311
- if (!pending) return
312
-
313
- clearTimeout(pending.timer)
314
- this.pendingRequests.delete(msg.id)
315
-
316
- if (msg.error) {
317
- pending.reject(new Error(`JSON-RPC error ${msg.error.code}: ${msg.error.message}`))
318
- } else {
319
- pending.resolve(msg.result)
320
- }
321
- }
322
-
323
- // ---------------------------------------------------------------------------
324
- // Health checks
325
- // ---------------------------------------------------------------------------
326
-
327
- /**
328
- * Ping a server — checks process liveness and sends a JSON-RPC `ping`.
329
- * Updates `entry.healthy`.
330
- */
331
- async pingServer(name: string): Promise<boolean> {
332
- const entry = this.servers.get(name)
333
- if (!entry) return false
334
-
335
- // Process liveness check
336
- if (!entry.process || entry.process.exitCode !== null) {
337
- entry.healthy = false
338
- return false
339
- }
340
-
341
- entry.lastPingAt = Date.now()
342
-
343
- try {
344
- await this.sendRequest(name, 'ping')
345
- entry.healthy = true
346
- return true
347
- } catch {
348
- // ping not supported by all servers — still healthy if process is alive
349
- entry.healthy = entry.process.exitCode === null
350
- return entry.healthy
351
- }
352
- }
353
-
354
- // ---------------------------------------------------------------------------
355
- // Tool discovery
356
- // ---------------------------------------------------------------------------
357
-
358
- /**
359
- * Discover tools from a running server via JSON-RPC `tools/list`.
360
- * Caches the result in the server entry.
361
- */
362
- async listServerTools(name: string): Promise<MCPTool[]> {
363
- const entry = this.servers.get(name)
364
- if (!entry) throw new Error(`Unknown server: "${name}"`)
365
-
366
- const result = await this.sendRequest(name, 'tools/list')
367
-
368
- const tools = (result as { tools?: MCPTool[] })?.tools ?? []
369
- entry.tools = tools
370
- return tools
371
- }
372
-
373
- /**
374
- * Return all tools from all healthy servers, namespaced as
375
- * `@@mcp_{serverName}_{toolName}` to avoid collisions.
376
- */
377
- getAllTools(): NamespacedTool[] {
378
- const tools: NamespacedTool[] = []
379
-
380
- for (const [serverName, entry] of this.servers) {
381
- if (!entry.healthy) continue
382
-
383
- for (const tool of entry.tools) {
384
- tools.push({
385
- namespacedName: `${MCP_TOOL_PREFIX}_${serverName}_${tool.name}`,
386
- serverName,
387
- tool,
388
- })
389
- }
390
- }
391
-
392
- return tools
393
- }
394
-
395
- /**
396
- * Call a tool on a running MCP server via JSON-RPC `tools/call`.
397
- *
398
- * @param serverName - The registered server name
399
- * @param toolName - The tool name (without namespace prefix)
400
- * @param args - Arguments to pass to the tool
401
- */
402
- async callTool(serverName: string, toolName: string, args: unknown): Promise<unknown> {
403
- return this.sendRequest(serverName, 'tools/call', {
404
- name: toolName,
405
- arguments: args,
406
- })
407
- }
408
-
409
- /**
410
- * Return the health status of all registered servers.
411
- */
412
- getStatus(): Record<string, { healthy: boolean; toolCount: number; pid: number | null }> {
413
- const status: Record<string, { healthy: boolean; toolCount: number; pid: number | null }> = {}
414
- for (const [name, entry] of this.servers) {
415
- status[name] = {
416
- healthy: entry.healthy,
417
- toolCount: entry.tools.length,
418
- pid: entry.process?.pid ?? null,
419
- }
420
- }
421
- return status
422
- }
423
-
424
- // ---------------------------------------------------------------------------
425
- // Health check loop
426
- // ---------------------------------------------------------------------------
427
-
428
- private startHealthCheckLoop(): void {
429
- this.healthCheckTimer = setInterval(async () => {
430
- for (const [name] of this.servers) {
431
- try {
432
- await this.pingServer(name)
433
- } catch {
434
- // Already handled inside pingServer
435
- }
436
- }
437
- }, HEALTH_CHECK_INTERVAL_MS)
438
-
439
- // Don't prevent process exit
440
- this.healthCheckTimer.unref?.()
441
- }
442
-
443
- private stopHealthCheckLoop(): void {
444
- if (this.healthCheckTimer) {
445
- clearInterval(this.healthCheckTimer)
446
- this.healthCheckTimer = null
447
- }
448
- }
449
-
450
- // ---------------------------------------------------------------------------
451
- // Testing utilities
452
- // ---------------------------------------------------------------------------
453
-
454
- /**
455
- * Reset the singleton (for testing only).
456
- * @internal
457
- */
458
- static _resetForTests(): void {
459
- if (MCPHypervisor.instance) {
460
- MCPHypervisor.instance.stopHealthCheckLoop()
461
- MCPHypervisor.instance = null
462
- }
463
- }
464
- }