@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,643 +0,0 @@
1
- #!/usr/bin/env tsx
2
-
3
- /**
4
- * MCP Adapter - Generic Model Context Protocol Integration
5
- *
6
- * Provides a unified interface for all MCP server integrations,
7
- * eliminating code duplication across different service adapters.
8
- *
9
- * Usage:
10
- * const adapter = new MCPAdapter('vercel', config)
11
- * await adapter.execute(request)
12
- */
13
-
14
- import { randomBytes } from 'node:crypto'
15
- import { registerCleanupHandler } from '@revealui/core/monitoring'
16
- import { logger as coreLogger } from '@revealui/core/observability/logger'
17
- import { createLogger } from '@revealui/scripts'
18
- import { ErrorCode, ScriptError } from '@revealui/scripts/errors'
19
-
20
- // =============================================================================
21
- // Global Adapter Registry
22
- // =============================================================================
23
-
24
- /**
25
- * Track all active MCP adapters for cleanup
26
- */
27
- const activeAdapters: Set<MCPAdapter> = new Set()
28
-
29
- /**
30
- * Dispose all active MCP adapters (cleanup on shutdown)
31
- */
32
- export function disposeAllAdapters(): void {
33
- for (const adapter of activeAdapters) {
34
- try {
35
- adapter.dispose()
36
- } catch (error) {
37
- coreLogger.error(
38
- 'Failed to dispose adapter',
39
- error instanceof Error ? error : new Error(String(error)),
40
- )
41
- }
42
- }
43
- activeAdapters.clear()
44
- }
45
-
46
- // Register cleanup handler
47
- let cleanupHandlerRegistered = false
48
- function registerAdapterCleanup() {
49
- if (cleanupHandlerRegistered) return
50
-
51
- registerCleanupHandler(
52
- 'mcp-adapters',
53
- () => {
54
- disposeAllAdapters()
55
- },
56
- 'Dispose all MCP adapters',
57
- 90, // High priority
58
- )
59
-
60
- cleanupHandlerRegistered = true
61
- }
62
-
63
- export interface MCPRequest {
64
- action: string
65
- parameters?: Record<string, unknown>
66
- options?: {
67
- timeout?: number
68
- retries?: number
69
- dryRun?: boolean
70
- /** Idempotency key to prevent duplicate operations */
71
- idempotencyKey?: string
72
- /** TTL for idempotency cache in milliseconds (default: 5 minutes) */
73
- idempotencyTTL?: number
74
- }
75
- }
76
-
77
- export interface MCPResponse {
78
- success: boolean
79
- data?: unknown
80
- error?: string
81
- metadata?: {
82
- duration: number
83
- retries: number
84
- service: string
85
- /** Indicates this response was served from idempotency cache */
86
- cached?: boolean
87
- /** The idempotency key that was used */
88
- idempotencyKey?: string
89
- }
90
- }
91
-
92
- // =============================================================================
93
- // Idempotency Cache
94
- // =============================================================================
95
-
96
- interface CachedResponse {
97
- response: MCPResponse
98
- expiresAt: number
99
- }
100
-
101
- /**
102
- * In-memory idempotency cache for preventing duplicate operations.
103
- * Each adapter instance has its own cache.
104
- */
105
- class IdempotencyCache {
106
- private cache = new Map<string, CachedResponse>()
107
- private cleanupInterval: ReturnType<typeof setInterval> | null = null
108
- // biome-ignore lint/style/useNamingConvention: Constant should be uppercase
109
- private readonly DEFAULT_TTL = 5 * 60 * 1000 // 5 minutes
110
-
111
- constructor() {
112
- // Cleanup expired entries every minute
113
- this.cleanupInterval = setInterval(() => this.cleanup(), 60 * 1000)
114
- }
115
-
116
- /**
117
- * Get a cached response by idempotency key
118
- */
119
- get(key: string): MCPResponse | null {
120
- const cached = this.cache.get(key)
121
- if (!cached) return null
122
-
123
- if (Date.now() > cached.expiresAt) {
124
- this.cache.delete(key)
125
- return null
126
- }
127
-
128
- return {
129
- ...cached.response,
130
- metadata: {
131
- ...cached.response.metadata,
132
- cached: true,
133
- idempotencyKey: key,
134
- },
135
- } as MCPResponse
136
- }
137
-
138
- /**
139
- * Store a response with idempotency key
140
- */
141
- set(key: string, response: MCPResponse, ttl?: number): void {
142
- const expiresAt = Date.now() + (ttl || this.DEFAULT_TTL)
143
- this.cache.set(key, { response, expiresAt })
144
- }
145
-
146
- /**
147
- * Check if a key exists in the cache
148
- */
149
- has(key: string): boolean {
150
- const cached = this.cache.get(key)
151
- if (!cached) return false
152
-
153
- if (Date.now() > cached.expiresAt) {
154
- this.cache.delete(key)
155
- return false
156
- }
157
-
158
- return true
159
- }
160
-
161
- /**
162
- * Remove expired entries
163
- */
164
- private cleanup(): void {
165
- const now = Date.now()
166
- for (const [key, value] of this.cache.entries()) {
167
- if (now > value.expiresAt) {
168
- this.cache.delete(key)
169
- }
170
- }
171
- }
172
-
173
- /**
174
- * Clear all cached entries
175
- */
176
- clear(): void {
177
- this.cache.clear()
178
- }
179
-
180
- /**
181
- * Stop the cleanup interval
182
- */
183
- dispose(): void {
184
- if (this.cleanupInterval) {
185
- clearInterval(this.cleanupInterval)
186
- this.cleanupInterval = null
187
- }
188
- }
189
-
190
- /**
191
- * Get cache statistics
192
- */
193
- stats(): { size: number; keys: string[] } {
194
- return {
195
- size: this.cache.size,
196
- keys: Array.from(this.cache.keys()),
197
- }
198
- }
199
- }
200
-
201
- export interface MCPConfig {
202
- apiKey?: string
203
- baseUrl?: string
204
- timeout?: number
205
- retries?: number
206
- environment?: 'development' | 'production'
207
- }
208
-
209
- export abstract class MCPAdapter {
210
- protected serviceName: string
211
- protected config: MCPConfig
212
- protected logger = createLogger()
213
- protected idempotencyCache = new IdempotencyCache()
214
-
215
- constructor(serviceName: string, config: MCPConfig) {
216
- this.serviceName = serviceName
217
- this.config = {
218
- timeout: 30000,
219
- retries: 3,
220
- environment: 'development',
221
- ...config,
222
- }
223
-
224
- // Register adapter for cleanup
225
- activeAdapters.add(this)
226
- registerAdapterCleanup()
227
- }
228
-
229
- /**
230
- * Dispose of adapter resources (cleanup idempotency cache)
231
- */
232
- dispose(): void {
233
- this.idempotencyCache.dispose()
234
- activeAdapters.delete(this)
235
- }
236
-
237
- /**
238
- * Get idempotency cache statistics
239
- */
240
- getCacheStats(): { size: number; keys: string[] } {
241
- return this.idempotencyCache.stats()
242
- }
243
-
244
- /**
245
- * Clear the idempotency cache
246
- */
247
- clearCache(): void {
248
- this.idempotencyCache.clear()
249
- }
250
-
251
- /**
252
- * Execute an MCP request
253
- *
254
- * If an idempotencyKey is provided in options, the request will be checked
255
- * against the cache. If a cached response exists, it will be returned
256
- * immediately. Otherwise, the request will be executed and the response
257
- * will be cached for future duplicate requests.
258
- */
259
- async execute(request: MCPRequest): Promise<MCPResponse> {
260
- const startTime = Date.now()
261
- let attempts = 0
262
- const idempotencyKey = request.options?.idempotencyKey
263
-
264
- try {
265
- this.validateRequest(request)
266
-
267
- // Check idempotency cache first
268
- if (idempotencyKey) {
269
- const cached = this.idempotencyCache.get(idempotencyKey)
270
- if (cached) {
271
- this.logger.info(
272
- `[${this.serviceName}] Returning cached response for idempotency key: ${idempotencyKey}`,
273
- )
274
- return cached
275
- }
276
- }
277
-
278
- if (request.options?.dryRun) {
279
- return this.createDryRunResponse(request)
280
- }
281
-
282
- while (attempts < (request.options?.retries || this.config.retries || 3)) {
283
- attempts++
284
-
285
- try {
286
- this.logger.info(
287
- `[${this.serviceName}] Executing ${request.action} (attempt ${attempts})`,
288
- )
289
-
290
- const result = await this.executeRequest(request)
291
-
292
- const duration = Date.now() - startTime
293
- const response: MCPResponse = {
294
- success: true,
295
- data: result,
296
- metadata: {
297
- duration,
298
- retries: attempts - 1,
299
- service: this.serviceName,
300
- ...(idempotencyKey && { idempotencyKey }),
301
- },
302
- }
303
-
304
- // Cache successful response if idempotency key provided
305
- if (idempotencyKey) {
306
- this.idempotencyCache.set(idempotencyKey, response, request.options?.idempotencyTTL)
307
- }
308
-
309
- return response
310
- } catch (error) {
311
- this.logger.warning(`[${this.serviceName}] Attempt ${attempts} failed: ${error}`)
312
-
313
- if (attempts >= (request.options?.retries || this.config.retries || 3)) {
314
- throw error
315
- }
316
-
317
- // Wait before retry (exponential backoff)
318
- const delay = Math.min(1000 * 2 ** (attempts - 1), 10000)
319
- await new Promise((resolve) => setTimeout(resolve, delay))
320
- }
321
- }
322
-
323
- throw new ScriptError('All retry attempts exhausted', ErrorCode.TIMEOUT_ERROR)
324
- } catch (error) {
325
- const duration = Date.now() - startTime
326
- const response: MCPResponse = {
327
- success: false,
328
- error: error instanceof Error ? error.message : String(error),
329
- metadata: {
330
- duration,
331
- retries: attempts,
332
- service: this.serviceName,
333
- ...(idempotencyKey && { idempotencyKey }),
334
- },
335
- }
336
-
337
- // Also cache failed responses to prevent duplicate attempts
338
- // This prevents the same failing request from being retried repeatedly
339
- if (idempotencyKey) {
340
- this.idempotencyCache.set(idempotencyKey, response, request.options?.idempotencyTTL)
341
- }
342
-
343
- return response
344
- }
345
- }
346
-
347
- /**
348
- * Validate the incoming request
349
- */
350
- protected validateRequest(request: MCPRequest): void {
351
- if (!request.action) {
352
- throw new ScriptError('Request must include an action', ErrorCode.VALIDATION_ERROR)
353
- }
354
-
355
- if (!this.isValidAction(request.action)) {
356
- throw new ScriptError(`Unsupported action: ${request.action}`, ErrorCode.VALIDATION_ERROR)
357
- }
358
- }
359
-
360
- /**
361
- * Check if an action is supported by this adapter
362
- */
363
- protected abstract isValidAction(action: string): boolean
364
-
365
- /**
366
- * Execute the actual request (implemented by subclasses)
367
- */
368
- protected abstract executeRequest(request: MCPRequest): Promise<unknown>
369
-
370
- /**
371
- * Create a dry-run response
372
- */
373
- protected createDryRunResponse(request: MCPRequest): MCPResponse {
374
- return {
375
- success: true,
376
- data: {
377
- dryRun: true,
378
- action: request.action,
379
- parameters: request.parameters,
380
- message: `Would execute ${request.action} on ${this.serviceName}`,
381
- },
382
- }
383
- }
384
-
385
- /**
386
- * Get authentication headers for API calls
387
- */
388
- protected getAuthHeaders(): Record<string, string> {
389
- const headers: Record<string, string> = {
390
- 'Content-Type': 'application/json',
391
- 'User-Agent': `RevealUI-MCP/${this.serviceName}`,
392
- }
393
-
394
- if (this.config.apiKey) {
395
- // Different services use different header names
396
- const headerName = this.getAuthHeaderName()
397
- headers[headerName] = this.config.apiKey
398
- }
399
-
400
- return headers
401
- }
402
-
403
- /**
404
- * Get the authentication header name for this service
405
- */
406
- protected abstract getAuthHeaderName(): string
407
-
408
- /**
409
- * Make an HTTP request with proper error handling
410
- */
411
- protected async makeRequest(
412
- method: 'GET' | 'POST' | 'PUT' | 'DELETE',
413
- url: string,
414
- data?: unknown,
415
- ): Promise<unknown> {
416
- const headers = this.getAuthHeaders()
417
- const timeout = this.config.timeout || 30000
418
-
419
- const controller = new AbortController()
420
- const timer = setTimeout(() => controller.abort(), timeout)
421
-
422
- try {
423
- const response = await fetch(url, {
424
- method,
425
- headers,
426
- body: data && (method === 'POST' || method === 'PUT') ? JSON.stringify(data) : undefined,
427
- signal: controller.signal,
428
- })
429
-
430
- if (!response.ok) {
431
- throw new ScriptError(
432
- `HTTP ${response.status} ${response.statusText}`,
433
- ErrorCode.NETWORK_ERROR,
434
- )
435
- }
436
-
437
- const contentType = response.headers.get('content-type') ?? ''
438
- if (contentType.includes('application/json')) {
439
- return await response.json()
440
- }
441
- return await response.text()
442
- } catch (error) {
443
- if (error instanceof ScriptError) throw error
444
- throw new ScriptError(
445
- `Request to ${this.serviceName} failed: ${error}`,
446
- ErrorCode.NETWORK_ERROR,
447
- )
448
- } finally {
449
- clearTimeout(timer)
450
- }
451
- }
452
- }
453
-
454
- // Specific service adapters
455
-
456
- export class VercelAdapter extends MCPAdapter {
457
- constructor(config: MCPConfig) {
458
- super('vercel', config)
459
- }
460
-
461
- protected isValidAction(action: string): boolean {
462
- return ['deploy', 'list-deployments', 'get-deployment', 'delete-deployment'].includes(action)
463
- }
464
-
465
- protected getAuthHeaderName(): string {
466
- return 'Authorization'
467
- }
468
-
469
- protected async executeRequest(request: MCPRequest): Promise<unknown> {
470
- const baseUrl = this.config.baseUrl || 'https://api.vercel.com'
471
-
472
- switch (request.action) {
473
- case 'deploy':
474
- return this.makeRequest('POST', `${baseUrl}/v13/deployments`, request.parameters)
475
-
476
- case 'list-deployments':
477
- return this.makeRequest('GET', `${baseUrl}/v6/deployments`)
478
-
479
- case 'get-deployment': {
480
- const { id } = request.parameters || {}
481
- if (!id) throw new ScriptError('Deployment ID required', ErrorCode.VALIDATION_ERROR)
482
- return this.makeRequest('GET', `${baseUrl}/v13/deployments/${String(id)}`)
483
- }
484
-
485
- case 'delete-deployment': {
486
- const { deploymentId } = request.parameters || {}
487
- if (!deploymentId)
488
- throw new ScriptError('Deployment ID required', ErrorCode.VALIDATION_ERROR)
489
- return this.makeRequest('DELETE', `${baseUrl}/v13/deployments/${String(deploymentId)}`)
490
- }
491
-
492
- default:
493
- throw new ScriptError(`Unsupported action: ${request.action}`, ErrorCode.VALIDATION_ERROR)
494
- }
495
- }
496
- }
497
-
498
- export class StripeAdapter extends MCPAdapter {
499
- constructor(config: MCPConfig) {
500
- super('stripe', config)
501
- }
502
-
503
- protected isValidAction(action: string): boolean {
504
- return [
505
- 'create-payment-intent',
506
- 'list-payment-intents',
507
- 'create-customer',
508
- 'list-customers',
509
- ].includes(action)
510
- }
511
-
512
- protected getAuthHeaderName(): string {
513
- return 'Authorization'
514
- }
515
-
516
- protected async executeRequest(request: MCPRequest): Promise<unknown> {
517
- const baseUrl = this.config.baseUrl || 'https://api.stripe.com/v1'
518
-
519
- switch (request.action) {
520
- case 'create-payment-intent':
521
- return this.makeRequest('POST', `${baseUrl}/payment_intents`, request.parameters)
522
-
523
- case 'list-payment-intents':
524
- return this.makeRequest('GET', `${baseUrl}/payment_intents`)
525
-
526
- case 'create-customer':
527
- return this.makeRequest('POST', `${baseUrl}/customers`, request.parameters)
528
-
529
- case 'list-customers':
530
- return this.makeRequest('GET', `${baseUrl}/customers`)
531
-
532
- default:
533
- throw new ScriptError(`Unsupported action: ${request.action}`, ErrorCode.VALIDATION_ERROR)
534
- }
535
- }
536
- }
537
-
538
- export class NeonAdapter extends MCPAdapter {
539
- constructor(config: MCPConfig) {
540
- super('neon', config)
541
- }
542
-
543
- protected isValidAction(action: string): boolean {
544
- return ['list-projects', 'create-project', 'get-project', 'delete-project'].includes(action)
545
- }
546
-
547
- protected getAuthHeaderName(): string {
548
- return 'Authorization'
549
- }
550
-
551
- protected async executeRequest(request: MCPRequest): Promise<unknown> {
552
- const baseUrl = this.config.baseUrl || 'https://console.neon.tech/api/v2'
553
-
554
- switch (request.action) {
555
- case 'list-projects':
556
- return this.makeRequest('GET', `${baseUrl}/projects`)
557
-
558
- case 'create-project':
559
- return this.makeRequest('POST', `${baseUrl}/projects`, request.parameters)
560
-
561
- case 'get-project': {
562
- const { id } = request.parameters || {}
563
- if (!id) throw new ScriptError('Project ID required', ErrorCode.VALIDATION_ERROR)
564
- return this.makeRequest('GET', `${baseUrl}/projects/${String(id)}`)
565
- }
566
-
567
- case 'delete-project': {
568
- const { projectId } = request.parameters || {}
569
- if (!projectId) throw new ScriptError('Project ID required', ErrorCode.VALIDATION_ERROR)
570
- return this.makeRequest('DELETE', `${baseUrl}/projects/${String(projectId)}`)
571
- }
572
-
573
- default:
574
- throw new ScriptError(`Unsupported action: ${request.action}`, ErrorCode.VALIDATION_ERROR)
575
- }
576
- }
577
- }
578
-
579
- // Factory function to create adapters
580
- export function createMCPAdapter(service: string, config: MCPConfig): MCPAdapter {
581
- switch (service.toLowerCase()) {
582
- case 'vercel':
583
- return new VercelAdapter(config)
584
- case 'stripe':
585
- return new StripeAdapter(config)
586
- case 'neon':
587
- return new NeonAdapter(config)
588
- default:
589
- throw new ScriptError(`Unsupported MCP service: ${service}`, ErrorCode.CONFIG_ERROR)
590
- }
591
- }
592
-
593
- /**
594
- * Generate an idempotency key based on the request content.
595
- *
596
- * This creates a deterministic key from the action and parameters,
597
- * so identical requests will get the same key.
598
- *
599
- * @example
600
- * ```typescript
601
- * const key = generateIdempotencyKey({
602
- * action: 'deploy',
603
- * parameters: { projectId: '123' }
604
- * })
605
- * // Returns: "deploy:a1b2c3d4e5f6..."
606
- * ```
607
- */
608
- export function generateIdempotencyKey(request: MCPRequest): string {
609
- const content = JSON.stringify({
610
- action: request.action,
611
- parameters: request.parameters || {},
612
- })
613
-
614
- // Simple hash function for generating consistent keys
615
- let hash = 0
616
- for (let i = 0; i < content.length; i++) {
617
- const char = content.charCodeAt(i)
618
- hash = (hash << 5) - hash + char
619
- hash = hash & hash // Convert to 32-bit integer
620
- }
621
-
622
- // Convert to positive hex string
623
- const hashHex = Math.abs(hash).toString(16).padStart(8, '0')
624
- return `${request.action}:${hashHex}`
625
- }
626
-
627
- /**
628
- * Generate a unique idempotency key with timestamp.
629
- *
630
- * Use this when you want each request to be unique but still
631
- * want idempotency protection against rapid duplicate submissions.
632
- *
633
- * @example
634
- * ```typescript
635
- * const key = generateUniqueIdempotencyKey('deploy')
636
- * // Returns: "deploy:1706536800000:a1b2c3d4"
637
- * ```
638
- */
639
- export function generateUniqueIdempotencyKey(action: string): string {
640
- const timestamp = Date.now()
641
- const random = randomBytes(6).toString('hex')
642
- return `${action}:${timestamp}:${random}`
643
- }