@revealui/mcp 0.0.1-pre.0 → 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 (270) hide show
  1. package/.env.example +9 -0
  2. package/MCP_MAINTENANCE.md +265 -0
  3. package/README.md +260 -0
  4. package/__tests__/crdt.integration.test.ts +156 -0
  5. package/configs/README.md +77 -0
  6. package/configs/claude-template.json +54 -0
  7. package/dist/packages/core/src/database/ssl-config.d.ts +9 -0
  8. package/dist/packages/core/src/database/ssl-config.d.ts.map +1 -0
  9. package/dist/packages/core/src/database/ssl-config.js +8 -0
  10. package/dist/packages/core/src/database/ssl-config.js.map +1 -0
  11. package/dist/packages/core/src/features.d.ts +86 -0
  12. package/dist/packages/core/src/features.d.ts.map +1 -0
  13. package/dist/packages/core/src/features.js +93 -0
  14. package/dist/packages/core/src/features.js.map +1 -0
  15. package/dist/packages/core/src/license.d.ts +75 -0
  16. package/dist/packages/core/src/license.d.ts.map +1 -0
  17. package/dist/packages/core/src/license.js +174 -0
  18. package/dist/packages/core/src/license.js.map +1 -0
  19. package/dist/packages/core/src/monitoring/alerts.d.ts +118 -0
  20. package/dist/packages/core/src/monitoring/alerts.d.ts.map +1 -0
  21. package/dist/packages/core/src/monitoring/alerts.js +325 -0
  22. package/dist/packages/core/src/monitoring/alerts.js.map +1 -0
  23. package/dist/packages/core/src/monitoring/cleanup-manager.d.ts +71 -0
  24. package/dist/packages/core/src/monitoring/cleanup-manager.d.ts.map +1 -0
  25. package/dist/packages/core/src/monitoring/cleanup-manager.js +227 -0
  26. package/dist/packages/core/src/monitoring/cleanup-manager.js.map +1 -0
  27. package/dist/packages/core/src/monitoring/health-monitor.d.ts +22 -0
  28. package/dist/packages/core/src/monitoring/health-monitor.d.ts.map +1 -0
  29. package/dist/packages/core/src/monitoring/health-monitor.js +143 -0
  30. package/dist/packages/core/src/monitoring/health-monitor.js.map +1 -0
  31. package/dist/packages/core/src/monitoring/index.d.ts +14 -0
  32. package/dist/packages/core/src/monitoring/index.d.ts.map +1 -0
  33. package/dist/packages/core/src/monitoring/index.js +18 -0
  34. package/dist/packages/core/src/monitoring/index.js.map +1 -0
  35. package/dist/packages/core/src/monitoring/process-registry.d.ts +97 -0
  36. package/dist/packages/core/src/monitoring/process-registry.d.ts.map +1 -0
  37. package/dist/packages/core/src/monitoring/process-registry.js +223 -0
  38. package/dist/packages/core/src/monitoring/process-registry.js.map +1 -0
  39. package/dist/packages/core/src/monitoring/types.d.ts +231 -0
  40. package/dist/packages/core/src/monitoring/types.d.ts.map +1 -0
  41. package/dist/packages/core/src/monitoring/types.js +43 -0
  42. package/dist/packages/core/src/monitoring/types.js.map +1 -0
  43. package/dist/packages/core/src/monitoring/zombie-detector.d.ts +81 -0
  44. package/dist/packages/core/src/monitoring/zombie-detector.d.ts.map +1 -0
  45. package/dist/packages/core/src/monitoring/zombie-detector.js +232 -0
  46. package/dist/packages/core/src/monitoring/zombie-detector.js.map +1 -0
  47. package/dist/packages/core/src/observability/logger.d.ts +47 -0
  48. package/dist/packages/core/src/observability/logger.d.ts.map +1 -0
  49. package/dist/packages/core/src/observability/logger.js +141 -0
  50. package/dist/packages/core/src/observability/logger.js.map +1 -0
  51. package/dist/packages/core/src/utils/logger-server.d.ts +32 -0
  52. package/dist/packages/core/src/utils/logger-server.d.ts.map +1 -0
  53. package/dist/packages/core/src/utils/logger-server.js +69 -0
  54. package/dist/packages/core/src/utils/logger-server.js.map +1 -0
  55. package/dist/packages/core/src/utils/request-context.d.ts +143 -0
  56. package/dist/packages/core/src/utils/request-context.d.ts.map +1 -0
  57. package/dist/packages/core/src/utils/request-context.js +169 -0
  58. package/dist/packages/core/src/utils/request-context.js.map +1 -0
  59. package/dist/packages/dev/src/code-validator/index.d.ts +20 -0
  60. package/dist/packages/dev/src/code-validator/index.d.ts.map +1 -0
  61. package/dist/packages/dev/src/code-validator/index.js +20 -0
  62. package/dist/packages/dev/src/code-validator/index.js.map +1 -0
  63. package/dist/packages/dev/src/code-validator/types.d.ts +67 -0
  64. package/dist/packages/dev/src/code-validator/types.d.ts.map +1 -0
  65. package/dist/packages/dev/src/code-validator/types.js +7 -0
  66. package/dist/packages/dev/src/code-validator/types.js.map +1 -0
  67. package/dist/packages/dev/src/code-validator/validator.d.ts +48 -0
  68. package/dist/packages/dev/src/code-validator/validator.d.ts.map +1 -0
  69. package/dist/packages/dev/src/code-validator/validator.js +176 -0
  70. package/dist/packages/dev/src/code-validator/validator.js.map +1 -0
  71. package/dist/packages/mcp/src/adapters/db.d.ts +46 -0
  72. package/dist/packages/mcp/src/adapters/db.d.ts.map +1 -0
  73. package/dist/packages/mcp/src/adapters/db.js +127 -0
  74. package/dist/packages/mcp/src/adapters/db.js.map +1 -0
  75. package/dist/packages/mcp/src/config/index.d.ts +11 -0
  76. package/dist/packages/mcp/src/config/index.d.ts.map +1 -0
  77. package/dist/packages/mcp/src/config/index.js +18 -0
  78. package/dist/packages/mcp/src/config/index.js.map +1 -0
  79. package/dist/packages/mcp/src/contracts.d.ts +131 -0
  80. package/dist/packages/mcp/src/contracts.d.ts.map +1 -0
  81. package/dist/packages/mcp/src/contracts.js +153 -0
  82. package/dist/packages/mcp/src/contracts.js.map +1 -0
  83. package/dist/packages/mcp/src/hypervisor.d.ts +132 -0
  84. package/dist/packages/mcp/src/hypervisor.d.ts.map +1 -0
  85. package/dist/packages/mcp/src/hypervisor.js +359 -0
  86. package/dist/packages/mcp/src/hypervisor.js.map +1 -0
  87. package/dist/packages/mcp/src/index.d.ts +25 -0
  88. package/dist/packages/mcp/src/index.d.ts.map +1 -0
  89. package/dist/packages/mcp/src/index.js +41 -0
  90. package/dist/packages/mcp/src/index.js.map +1 -0
  91. package/dist/packages/mcp/src/servers/adapter.d.ts +199 -0
  92. package/dist/packages/mcp/src/servers/adapter.d.ts.map +1 -0
  93. package/dist/packages/mcp/src/servers/adapter.js +487 -0
  94. package/dist/packages/mcp/src/servers/adapter.js.map +1 -0
  95. package/dist/packages/mcp/src/servers/code-validator.d.ts +24 -0
  96. package/dist/packages/mcp/src/servers/code-validator.d.ts.map +1 -0
  97. package/dist/packages/mcp/src/servers/code-validator.js +156 -0
  98. package/dist/packages/mcp/src/servers/code-validator.js.map +1 -0
  99. package/dist/packages/mcp/src/servers/neon.d.ts +11 -0
  100. package/dist/packages/mcp/src/servers/neon.d.ts.map +1 -0
  101. package/dist/packages/mcp/src/servers/neon.js +90 -0
  102. package/dist/packages/mcp/src/servers/neon.js.map +1 -0
  103. package/dist/packages/mcp/src/servers/next-devtools.d.ts +11 -0
  104. package/dist/packages/mcp/src/servers/next-devtools.d.ts.map +1 -0
  105. package/dist/packages/mcp/src/servers/next-devtools.js +215 -0
  106. package/dist/packages/mcp/src/servers/next-devtools.js.map +1 -0
  107. package/dist/packages/mcp/src/servers/playwright.d.ts +11 -0
  108. package/dist/packages/mcp/src/servers/playwright.d.ts.map +1 -0
  109. package/dist/packages/mcp/src/servers/playwright.js +68 -0
  110. package/dist/packages/mcp/src/servers/playwright.js.map +1 -0
  111. package/dist/packages/mcp/src/servers/stripe.d.ts +11 -0
  112. package/dist/packages/mcp/src/servers/stripe.d.ts.map +1 -0
  113. package/dist/packages/mcp/src/servers/stripe.js +86 -0
  114. package/dist/packages/mcp/src/servers/stripe.js.map +1 -0
  115. package/dist/packages/mcp/src/servers/supabase.d.ts +11 -0
  116. package/dist/packages/mcp/src/servers/supabase.d.ts.map +1 -0
  117. package/dist/packages/mcp/src/servers/supabase.js +144 -0
  118. package/dist/packages/mcp/src/servers/supabase.js.map +1 -0
  119. package/dist/packages/mcp/src/servers/vercel.d.ts +11 -0
  120. package/dist/packages/mcp/src/servers/vercel.d.ts.map +1 -0
  121. package/dist/packages/mcp/src/servers/vercel.js +87 -0
  122. package/dist/packages/mcp/src/servers/vercel.js.map +1 -0
  123. package/dist/packages/mcp/src/servers/vultr-test.d.ts +3 -0
  124. package/dist/packages/mcp/src/servers/vultr-test.d.ts.map +1 -0
  125. package/dist/packages/mcp/src/servers/vultr-test.js +82 -0
  126. package/dist/packages/mcp/src/servers/vultr-test.js.map +1 -0
  127. package/dist/scripts/lib/analyzers/console-analyzer.d.ts +188 -0
  128. package/dist/scripts/lib/analyzers/console-analyzer.d.ts.map +1 -0
  129. package/dist/scripts/lib/analyzers/console-analyzer.js +432 -0
  130. package/dist/scripts/lib/analyzers/console-analyzer.js.map +1 -0
  131. package/dist/scripts/lib/analyzers/index.d.ts +11 -0
  132. package/dist/scripts/lib/analyzers/index.d.ts.map +1 -0
  133. package/dist/scripts/lib/analyzers/index.js +11 -0
  134. package/dist/scripts/lib/analyzers/index.js.map +1 -0
  135. package/dist/scripts/lib/args.d.ts +104 -0
  136. package/dist/scripts/lib/args.d.ts.map +1 -0
  137. package/dist/scripts/lib/args.js +304 -0
  138. package/dist/scripts/lib/args.js.map +1 -0
  139. package/dist/scripts/lib/cache.d.ts +185 -0
  140. package/dist/scripts/lib/cache.d.ts.map +1 -0
  141. package/dist/scripts/lib/cache.js +390 -0
  142. package/dist/scripts/lib/cache.js.map +1 -0
  143. package/dist/scripts/lib/cli/dispatch.d.ts +116 -0
  144. package/dist/scripts/lib/cli/dispatch.d.ts.map +1 -0
  145. package/dist/scripts/lib/cli/dispatch.js +206 -0
  146. package/dist/scripts/lib/cli/dispatch.js.map +1 -0
  147. package/dist/scripts/lib/cli/index.d.ts +10 -0
  148. package/dist/scripts/lib/cli/index.d.ts.map +1 -0
  149. package/dist/scripts/lib/cli/index.js +10 -0
  150. package/dist/scripts/lib/cli/index.js.map +1 -0
  151. package/dist/scripts/lib/database/ssl-config.d.ts +26 -0
  152. package/dist/scripts/lib/database/ssl-config.d.ts.map +1 -0
  153. package/dist/scripts/lib/database/ssl-config.js +47 -0
  154. package/dist/scripts/lib/database/ssl-config.js.map +1 -0
  155. package/dist/scripts/lib/errors.d.ts +218 -0
  156. package/dist/scripts/lib/errors.d.ts.map +1 -0
  157. package/dist/scripts/lib/errors.js +543 -0
  158. package/dist/scripts/lib/errors.js.map +1 -0
  159. package/dist/scripts/lib/exec.d.ts +107 -0
  160. package/dist/scripts/lib/exec.d.ts.map +1 -0
  161. package/dist/scripts/lib/exec.js +232 -0
  162. package/dist/scripts/lib/exec.js.map +1 -0
  163. package/dist/scripts/lib/index.d.ts +50 -0
  164. package/dist/scripts/lib/index.d.ts.map +1 -0
  165. package/dist/scripts/lib/index.js +65 -0
  166. package/dist/scripts/lib/index.js.map +1 -0
  167. package/dist/scripts/lib/logger.d.ts +50 -0
  168. package/dist/scripts/lib/logger.d.ts.map +1 -0
  169. package/dist/scripts/lib/logger.js +159 -0
  170. package/dist/scripts/lib/logger.js.map +1 -0
  171. package/dist/scripts/lib/output.d.ts +149 -0
  172. package/dist/scripts/lib/output.d.ts.map +1 -0
  173. package/dist/scripts/lib/output.js +263 -0
  174. package/dist/scripts/lib/output.js.map +1 -0
  175. package/dist/scripts/lib/parallel.d.ts +164 -0
  176. package/dist/scripts/lib/parallel.d.ts.map +1 -0
  177. package/dist/scripts/lib/parallel.js +355 -0
  178. package/dist/scripts/lib/parallel.js.map +1 -0
  179. package/dist/scripts/lib/paths.d.ts +92 -0
  180. package/dist/scripts/lib/paths.d.ts.map +1 -0
  181. package/dist/scripts/lib/paths.js +171 -0
  182. package/dist/scripts/lib/paths.js.map +1 -0
  183. package/dist/scripts/lib/state/adapters/memory.d.ts +42 -0
  184. package/dist/scripts/lib/state/adapters/memory.d.ts.map +1 -0
  185. package/dist/scripts/lib/state/adapters/memory.js +110 -0
  186. package/dist/scripts/lib/state/adapters/memory.js.map +1 -0
  187. package/dist/scripts/lib/state/adapters/pglite.d.ts +46 -0
  188. package/dist/scripts/lib/state/adapters/pglite.d.ts.map +1 -0
  189. package/dist/scripts/lib/state/adapters/pglite.js +256 -0
  190. package/dist/scripts/lib/state/adapters/pglite.js.map +1 -0
  191. package/dist/scripts/lib/state/index.d.ts +16 -0
  192. package/dist/scripts/lib/state/index.d.ts.map +1 -0
  193. package/dist/scripts/lib/state/index.js +16 -0
  194. package/dist/scripts/lib/state/index.js.map +1 -0
  195. package/dist/scripts/lib/state/types.d.ts +111 -0
  196. package/dist/scripts/lib/state/types.d.ts.map +1 -0
  197. package/dist/scripts/lib/state/types.js +8 -0
  198. package/dist/scripts/lib/state/types.js.map +1 -0
  199. package/dist/scripts/lib/state/workflow-state.d.ts +110 -0
  200. package/dist/scripts/lib/state/workflow-state.d.ts.map +1 -0
  201. package/dist/scripts/lib/state/workflow-state.js +331 -0
  202. package/dist/scripts/lib/state/workflow-state.js.map +1 -0
  203. package/dist/scripts/lib/telemetry.d.ts +194 -0
  204. package/dist/scripts/lib/telemetry.d.ts.map +1 -0
  205. package/dist/scripts/lib/telemetry.js +394 -0
  206. package/dist/scripts/lib/telemetry.js.map +1 -0
  207. package/dist/scripts/lib/utils.d.ts +270 -0
  208. package/dist/scripts/lib/utils.d.ts.map +1 -0
  209. package/dist/scripts/lib/utils.js +473 -0
  210. package/dist/scripts/lib/utils.js.map +1 -0
  211. package/dist/scripts/lib/validation/database.d.ts +83 -0
  212. package/dist/scripts/lib/validation/database.d.ts.map +1 -0
  213. package/dist/scripts/lib/validation/database.js +199 -0
  214. package/dist/scripts/lib/validation/database.js.map +1 -0
  215. package/dist/scripts/lib/validation/env.d.ts +80 -0
  216. package/dist/scripts/lib/validation/env.d.ts.map +1 -0
  217. package/dist/scripts/lib/validation/env.js +246 -0
  218. package/dist/scripts/lib/validation/env.js.map +1 -0
  219. package/dist/scripts/lib/validation/index.d.ts +16 -0
  220. package/dist/scripts/lib/validation/index.d.ts.map +1 -0
  221. package/dist/scripts/lib/validation/index.js +16 -0
  222. package/dist/scripts/lib/validation/index.js.map +1 -0
  223. package/dist/scripts/lib/validation/post-execution.d.ts +74 -0
  224. package/dist/scripts/lib/validation/post-execution.d.ts.map +1 -0
  225. package/dist/scripts/lib/validation/post-execution.js +110 -0
  226. package/dist/scripts/lib/validation/post-execution.js.map +1 -0
  227. package/dist/scripts/lib/validation/pre-execution.d.ts +165 -0
  228. package/dist/scripts/lib/validation/pre-execution.d.ts.map +1 -0
  229. package/dist/scripts/lib/validation/pre-execution.js +466 -0
  230. package/dist/scripts/lib/validation/pre-execution.js.map +1 -0
  231. package/dist/scripts/lib/validators/documentation-validator.d.ts +242 -0
  232. package/dist/scripts/lib/validators/documentation-validator.d.ts.map +1 -0
  233. package/dist/scripts/lib/validators/documentation-validator.js +584 -0
  234. package/dist/scripts/lib/validators/documentation-validator.js.map +1 -0
  235. package/dist/scripts/lib/validators/index.d.ts +11 -0
  236. package/dist/scripts/lib/validators/index.d.ts.map +1 -0
  237. package/dist/scripts/lib/validators/index.js +11 -0
  238. package/dist/scripts/lib/validators/index.js.map +1 -0
  239. package/docker-compose.yml +46 -0
  240. package/docs/INDEX.md +88 -0
  241. package/docs/README.md +774 -0
  242. package/docs/SETUP.md +264 -0
  243. package/docs/servers/code-validator.md +586 -0
  244. package/eslint.config.js +7 -0
  245. package/migrations/0001_add_crdt_columns.sql +8 -0
  246. package/migrations/0001_rollback.sql +6 -0
  247. package/migrations/005_performance_indexes.sql +190 -0
  248. package/migrations/backfill_crdt_meta.js +45 -0
  249. package/package.json +21 -85
  250. package/src/__tests__/hypervisor.test.ts +212 -0
  251. package/src/adapters/db.ts +180 -0
  252. package/src/config/config.json +49 -0
  253. package/src/config/index.ts +30 -0
  254. package/src/contracts.ts +221 -0
  255. package/src/hypervisor.ts +464 -0
  256. package/src/index.ts +87 -0
  257. package/src/servers/adapter.ts +643 -0
  258. package/src/servers/code-validator.ts +188 -0
  259. package/src/servers/neon.ts +103 -0
  260. package/src/servers/next-devtools.ts +230 -0
  261. package/src/servers/playwright.ts +77 -0
  262. package/src/servers/stripe.ts +99 -0
  263. package/src/servers/supabase.ts +161 -0
  264. package/src/servers/vercel.ts +100 -0
  265. package/src/servers/vultr-test.ts +97 -0
  266. package/tsconfig.json +12 -0
  267. package/vitest.config.ts +22 -0
  268. package/LICENSE +0 -202
  269. package/dist/index.js +0 -10990
  270. package/dist/index.js.map +0 -1
@@ -0,0 +1,180 @@
1
+ /**
2
+ * DB adapter for MCP.
3
+ * - `connectPglite()` initializes ElectricSQL/pglite client with CRDT metadata.
4
+ * - `connectPostgres()` creates a standard Postgres client with Electric metadata.
5
+ * - `createMcpDbClient()` factory that selects adapter based on config.
6
+ *
7
+ * Uses @revealui/contracts as the single source of truth for CRDT operation types.
8
+ */
9
+
10
+ import { mkdir } from 'node:fs/promises'
11
+ import { dirname } from 'node:path'
12
+ import getMcpConfig from '@revealui/config/mcp'
13
+ import type { CrdtOperationsInsert, CrdtOperationsRow } from '@revealui/contracts'
14
+ import { getSSLConfig } from '@revealui/core/database/ssl-config'
15
+
16
+ export interface QueryResult<T = Record<string, unknown>> {
17
+ rows: T[]
18
+ affectedRows?: number
19
+ }
20
+
21
+ export type McpDbClient = {
22
+ query: <T = Record<string, unknown>>(sql: string, params?: unknown[]) => Promise<QueryResult<T>>
23
+ close: () => Promise<void>
24
+ }
25
+
26
+ /** Re-export contracts CRDT types for consumers */
27
+ export type { CrdtOperationsRow, CrdtOperationsInsert }
28
+
29
+ // Type for PGlite instance (minimal interface to avoid import issues)
30
+ interface PGliteInstance {
31
+ waitReady: Promise<void>
32
+ query<T = Record<string, unknown>>(
33
+ sql: string,
34
+ params?: unknown[],
35
+ ): Promise<{ rows: T[]; affectedRows?: number }>
36
+ exec(query: string): Promise<unknown>
37
+ close(): Promise<void>
38
+ }
39
+
40
+ // CRDT operations table schema for conflict-free replication
41
+ const CRDT_TABLE_SQL = `
42
+ CREATE TABLE IF NOT EXISTS crdt_operations (
43
+ id TEXT PRIMARY KEY,
44
+ document_id TEXT NOT NULL,
45
+ operation_type TEXT NOT NULL,
46
+ payload JSONB NOT NULL,
47
+ vector_clock JSONB NOT NULL,
48
+ node_id TEXT NOT NULL,
49
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
50
+ applied_at TIMESTAMPTZ
51
+ );
52
+ CREATE INDEX IF NOT EXISTS idx_crdt_ops_document ON crdt_operations(document_id);
53
+ CREATE INDEX IF NOT EXISTS idx_crdt_ops_node ON crdt_operations(node_id);
54
+ CREATE INDEX IF NOT EXISTS idx_crdt_ops_created ON crdt_operations(created_at DESC);
55
+ `
56
+
57
+ /**
58
+ * Connect to PGlite (embedded PostgreSQL) for local development/testing.
59
+ * Uses dynamic import to avoid bundling @electric-sql/pglite when not needed.
60
+ *
61
+ * @param options - Optional connection options
62
+ * @param options.dataDir - Override the default data directory. Use ':memory:' for in-memory.
63
+ */
64
+ export async function connectPglite(options?: { dataDir?: string }): Promise<McpDbClient> {
65
+ const cfg = getMcpConfig()
66
+
67
+ // Determine data directory from options, config, or default
68
+ // Use ':memory:' for in-memory database (useful for testing)
69
+ const dataDir = options?.dataDir || cfg.electricDatabaseUrl || '.revealui/mcp/pglite'
70
+
71
+ let db: PGliteInstance
72
+
73
+ try {
74
+ // Ensure directory exists if not in-memory
75
+ if (dataDir !== ':memory:') {
76
+ await mkdir(dirname(dataDir), { recursive: true })
77
+ }
78
+
79
+ const { PGlite } = await import('@electric-sql/pglite')
80
+ db = new PGlite(dataDir) as PGliteInstance
81
+ await db.waitReady
82
+ } catch (error) {
83
+ const err = error as Error
84
+ if (err.message?.includes('Cannot find module') || err.message?.includes('MODULE_NOT_FOUND')) {
85
+ throw new Error(
86
+ '@electric-sql/pglite is not installed. Run: pnpm add -D @electric-sql/pglite',
87
+ )
88
+ }
89
+ throw error
90
+ }
91
+
92
+ // Create CRDT operations table
93
+ await db.exec(CRDT_TABLE_SQL)
94
+
95
+ return {
96
+ async query<T = Record<string, unknown>>(
97
+ sql: string,
98
+ params?: unknown[],
99
+ ): Promise<QueryResult<T>> {
100
+ const result = await db.query(sql, params)
101
+ return {
102
+ rows: result.rows as T[],
103
+ affectedRows: result.affectedRows,
104
+ }
105
+ },
106
+ async close(): Promise<void> {
107
+ await db.close()
108
+ },
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Connect to PostgreSQL for production use.
114
+ * Supports Neon, Supabase, and generic PostgreSQL with SSL.
115
+ */
116
+ export async function connectPostgres(): Promise<McpDbClient> {
117
+ const cfg = getMcpConfig()
118
+
119
+ const connectionString =
120
+ cfg.electricDatabaseUrl ||
121
+ process.env.DATABASE_URL ||
122
+ process.env.POSTGRES_URL ||
123
+ process.env.SUPABASE_DATABASE_URI
124
+
125
+ if (!connectionString) {
126
+ throw new Error(
127
+ 'Database connection string not found. Set ELECTRIC_DATABASE_URL, DATABASE_URL, POSTGRES_URL, or SUPABASE_DATABASE_URI.',
128
+ )
129
+ }
130
+
131
+ const { Pool } = await import('pg')
132
+ const pool = new Pool({
133
+ connectionString,
134
+ ssl: getSSLConfig(connectionString),
135
+ })
136
+
137
+ // Test connection
138
+ const client = await pool.connect()
139
+ try {
140
+ await client.query('SELECT 1')
141
+ } finally {
142
+ client.release()
143
+ }
144
+
145
+ // Create CRDT operations table
146
+ await pool.query(CRDT_TABLE_SQL)
147
+
148
+ return {
149
+ async query<T = Record<string, unknown>>(
150
+ sql: string,
151
+ params?: unknown[],
152
+ ): Promise<QueryResult<T>> {
153
+ const result = await pool.query(sql, params)
154
+ return {
155
+ rows: result.rows as T[],
156
+ affectedRows: result.rowCount ?? undefined,
157
+ }
158
+ },
159
+ async close(): Promise<void> {
160
+ await pool.end()
161
+ },
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Factory function that creates an MCP database client based on configuration.
167
+ * Reads `persistenceDriver` from getMcpConfig() to determine which adapter to use.
168
+ */
169
+ export async function createMcpDbClient(): Promise<McpDbClient> {
170
+ const cfg = getMcpConfig()
171
+
172
+ if (cfg.persistenceDriver === 'postgres') {
173
+ return connectPostgres()
174
+ }
175
+
176
+ // Default to pglite for local development
177
+ return connectPglite()
178
+ }
179
+
180
+ export default { connectPglite, connectPostgres, createMcpDbClient }
@@ -0,0 +1,49 @@
1
+ {
2
+ "_comment": "MCP server configuration. This config is synchronized with .cursor/mcp-config.json (source of truth). All 6 servers are included for consistency.",
3
+ "_source_of_truth": ".cursor/mcp-config.json",
4
+ "_last_synced": "2025-01",
5
+ "mcpServers": {
6
+ "vercel": {
7
+ "command": "pnpm",
8
+ "args": ["mcp:vercel"],
9
+ "env": {
10
+ "VERCEL_API_KEY": "${VERCEL_API_KEY}",
11
+ "VERCEL_TOKEN": "${VERCEL_TOKEN}"
12
+ }
13
+ },
14
+ "stripe": {
15
+ "command": "pnpm",
16
+ "args": ["mcp:stripe"],
17
+ "env": {
18
+ "STRIPE_SECRET_KEY": "${STRIPE_SECRET_KEY}"
19
+ }
20
+ },
21
+ "neon": {
22
+ "command": "pnpm",
23
+ "args": ["mcp:neon"],
24
+ "env": {
25
+ "NEON_API_KEY": "${NEON_API_KEY}"
26
+ }
27
+ },
28
+ "supabase": {
29
+ "command": "pnpm",
30
+ "args": ["mcp:supabase"],
31
+ "env": {
32
+ "SUPABASE_URL": "${SUPABASE_URL}",
33
+ "SUPABASE_ANON_KEY": "${SUPABASE_ANON_KEY}",
34
+ "SUPABASE_SERVICE_ROLE_KEY": "${SUPABASE_SERVICE_ROLE_KEY}"
35
+ }
36
+ },
37
+ "playwright": {
38
+ "command": "pnpm",
39
+ "args": ["mcp:playwright"]
40
+ },
41
+ "next-devtools": {
42
+ "command": "pnpm",
43
+ "args": ["mcp:next-devtools"],
44
+ "env": {
45
+ "NEXT_TELEMETRY_DISABLED": "${NEXT_TELEMETRY_DISABLED:-0}"
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,30 @@
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
@@ -0,0 +1,221 @@
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
+ }