@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.
- package/.env.example +9 -0
- package/MCP_MAINTENANCE.md +265 -0
- package/README.md +260 -0
- package/__tests__/crdt.integration.test.ts +156 -0
- package/configs/README.md +77 -0
- package/configs/claude-template.json +54 -0
- package/dist/packages/core/src/database/ssl-config.d.ts +9 -0
- package/dist/packages/core/src/database/ssl-config.d.ts.map +1 -0
- package/dist/packages/core/src/database/ssl-config.js +8 -0
- package/dist/packages/core/src/database/ssl-config.js.map +1 -0
- package/dist/packages/core/src/features.d.ts +86 -0
- package/dist/packages/core/src/features.d.ts.map +1 -0
- package/dist/packages/core/src/features.js +93 -0
- package/dist/packages/core/src/features.js.map +1 -0
- package/dist/packages/core/src/license.d.ts +75 -0
- package/dist/packages/core/src/license.d.ts.map +1 -0
- package/dist/packages/core/src/license.js +174 -0
- package/dist/packages/core/src/license.js.map +1 -0
- package/dist/packages/core/src/monitoring/alerts.d.ts +118 -0
- package/dist/packages/core/src/monitoring/alerts.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/alerts.js +325 -0
- package/dist/packages/core/src/monitoring/alerts.js.map +1 -0
- package/dist/packages/core/src/monitoring/cleanup-manager.d.ts +71 -0
- package/dist/packages/core/src/monitoring/cleanup-manager.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/cleanup-manager.js +227 -0
- package/dist/packages/core/src/monitoring/cleanup-manager.js.map +1 -0
- package/dist/packages/core/src/monitoring/health-monitor.d.ts +22 -0
- package/dist/packages/core/src/monitoring/health-monitor.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/health-monitor.js +143 -0
- package/dist/packages/core/src/monitoring/health-monitor.js.map +1 -0
- package/dist/packages/core/src/monitoring/index.d.ts +14 -0
- package/dist/packages/core/src/monitoring/index.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/index.js +18 -0
- package/dist/packages/core/src/monitoring/index.js.map +1 -0
- package/dist/packages/core/src/monitoring/process-registry.d.ts +97 -0
- package/dist/packages/core/src/monitoring/process-registry.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/process-registry.js +223 -0
- package/dist/packages/core/src/monitoring/process-registry.js.map +1 -0
- package/dist/packages/core/src/monitoring/types.d.ts +231 -0
- package/dist/packages/core/src/monitoring/types.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/types.js +43 -0
- package/dist/packages/core/src/monitoring/types.js.map +1 -0
- package/dist/packages/core/src/monitoring/zombie-detector.d.ts +81 -0
- package/dist/packages/core/src/monitoring/zombie-detector.d.ts.map +1 -0
- package/dist/packages/core/src/monitoring/zombie-detector.js +232 -0
- package/dist/packages/core/src/monitoring/zombie-detector.js.map +1 -0
- package/dist/packages/core/src/observability/logger.d.ts +47 -0
- package/dist/packages/core/src/observability/logger.d.ts.map +1 -0
- package/dist/packages/core/src/observability/logger.js +141 -0
- package/dist/packages/core/src/observability/logger.js.map +1 -0
- package/dist/packages/core/src/utils/logger-server.d.ts +32 -0
- package/dist/packages/core/src/utils/logger-server.d.ts.map +1 -0
- package/dist/packages/core/src/utils/logger-server.js +69 -0
- package/dist/packages/core/src/utils/logger-server.js.map +1 -0
- package/dist/packages/core/src/utils/request-context.d.ts +143 -0
- package/dist/packages/core/src/utils/request-context.d.ts.map +1 -0
- package/dist/packages/core/src/utils/request-context.js +169 -0
- package/dist/packages/core/src/utils/request-context.js.map +1 -0
- package/dist/packages/dev/src/code-validator/index.d.ts +20 -0
- package/dist/packages/dev/src/code-validator/index.d.ts.map +1 -0
- package/dist/packages/dev/src/code-validator/index.js +20 -0
- package/dist/packages/dev/src/code-validator/index.js.map +1 -0
- package/dist/packages/dev/src/code-validator/types.d.ts +67 -0
- package/dist/packages/dev/src/code-validator/types.d.ts.map +1 -0
- package/dist/packages/dev/src/code-validator/types.js +7 -0
- package/dist/packages/dev/src/code-validator/types.js.map +1 -0
- package/dist/packages/dev/src/code-validator/validator.d.ts +48 -0
- package/dist/packages/dev/src/code-validator/validator.d.ts.map +1 -0
- package/dist/packages/dev/src/code-validator/validator.js +176 -0
- package/dist/packages/dev/src/code-validator/validator.js.map +1 -0
- package/dist/packages/mcp/src/adapters/db.d.ts +46 -0
- package/dist/packages/mcp/src/adapters/db.d.ts.map +1 -0
- package/dist/packages/mcp/src/adapters/db.js +127 -0
- package/dist/packages/mcp/src/adapters/db.js.map +1 -0
- package/dist/packages/mcp/src/config/index.d.ts +11 -0
- package/dist/packages/mcp/src/config/index.d.ts.map +1 -0
- package/dist/packages/mcp/src/config/index.js +18 -0
- package/dist/packages/mcp/src/config/index.js.map +1 -0
- package/dist/packages/mcp/src/contracts.d.ts +131 -0
- package/dist/packages/mcp/src/contracts.d.ts.map +1 -0
- package/dist/packages/mcp/src/contracts.js +153 -0
- package/dist/packages/mcp/src/contracts.js.map +1 -0
- package/dist/packages/mcp/src/hypervisor.d.ts +132 -0
- package/dist/packages/mcp/src/hypervisor.d.ts.map +1 -0
- package/dist/packages/mcp/src/hypervisor.js +359 -0
- package/dist/packages/mcp/src/hypervisor.js.map +1 -0
- package/dist/packages/mcp/src/index.d.ts +25 -0
- package/dist/packages/mcp/src/index.d.ts.map +1 -0
- package/dist/packages/mcp/src/index.js +41 -0
- package/dist/packages/mcp/src/index.js.map +1 -0
- package/dist/packages/mcp/src/servers/adapter.d.ts +199 -0
- package/dist/packages/mcp/src/servers/adapter.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/adapter.js +487 -0
- package/dist/packages/mcp/src/servers/adapter.js.map +1 -0
- package/dist/packages/mcp/src/servers/code-validator.d.ts +24 -0
- package/dist/packages/mcp/src/servers/code-validator.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/code-validator.js +156 -0
- package/dist/packages/mcp/src/servers/code-validator.js.map +1 -0
- package/dist/packages/mcp/src/servers/neon.d.ts +11 -0
- package/dist/packages/mcp/src/servers/neon.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/neon.js +90 -0
- package/dist/packages/mcp/src/servers/neon.js.map +1 -0
- package/dist/packages/mcp/src/servers/next-devtools.d.ts +11 -0
- package/dist/packages/mcp/src/servers/next-devtools.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/next-devtools.js +215 -0
- package/dist/packages/mcp/src/servers/next-devtools.js.map +1 -0
- package/dist/packages/mcp/src/servers/playwright.d.ts +11 -0
- package/dist/packages/mcp/src/servers/playwright.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/playwright.js +68 -0
- package/dist/packages/mcp/src/servers/playwright.js.map +1 -0
- package/dist/packages/mcp/src/servers/stripe.d.ts +11 -0
- package/dist/packages/mcp/src/servers/stripe.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/stripe.js +86 -0
- package/dist/packages/mcp/src/servers/stripe.js.map +1 -0
- package/dist/packages/mcp/src/servers/supabase.d.ts +11 -0
- package/dist/packages/mcp/src/servers/supabase.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/supabase.js +144 -0
- package/dist/packages/mcp/src/servers/supabase.js.map +1 -0
- package/dist/packages/mcp/src/servers/vercel.d.ts +11 -0
- package/dist/packages/mcp/src/servers/vercel.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/vercel.js +87 -0
- package/dist/packages/mcp/src/servers/vercel.js.map +1 -0
- package/dist/packages/mcp/src/servers/vultr-test.d.ts +3 -0
- package/dist/packages/mcp/src/servers/vultr-test.d.ts.map +1 -0
- package/dist/packages/mcp/src/servers/vultr-test.js +82 -0
- package/dist/packages/mcp/src/servers/vultr-test.js.map +1 -0
- package/dist/scripts/lib/analyzers/console-analyzer.d.ts +188 -0
- package/dist/scripts/lib/analyzers/console-analyzer.d.ts.map +1 -0
- package/dist/scripts/lib/analyzers/console-analyzer.js +432 -0
- package/dist/scripts/lib/analyzers/console-analyzer.js.map +1 -0
- package/dist/scripts/lib/analyzers/index.d.ts +11 -0
- package/dist/scripts/lib/analyzers/index.d.ts.map +1 -0
- package/dist/scripts/lib/analyzers/index.js +11 -0
- package/dist/scripts/lib/analyzers/index.js.map +1 -0
- package/dist/scripts/lib/args.d.ts +104 -0
- package/dist/scripts/lib/args.d.ts.map +1 -0
- package/dist/scripts/lib/args.js +304 -0
- package/dist/scripts/lib/args.js.map +1 -0
- package/dist/scripts/lib/cache.d.ts +185 -0
- package/dist/scripts/lib/cache.d.ts.map +1 -0
- package/dist/scripts/lib/cache.js +390 -0
- package/dist/scripts/lib/cache.js.map +1 -0
- package/dist/scripts/lib/cli/dispatch.d.ts +116 -0
- package/dist/scripts/lib/cli/dispatch.d.ts.map +1 -0
- package/dist/scripts/lib/cli/dispatch.js +206 -0
- package/dist/scripts/lib/cli/dispatch.js.map +1 -0
- package/dist/scripts/lib/cli/index.d.ts +10 -0
- package/dist/scripts/lib/cli/index.d.ts.map +1 -0
- package/dist/scripts/lib/cli/index.js +10 -0
- package/dist/scripts/lib/cli/index.js.map +1 -0
- package/dist/scripts/lib/database/ssl-config.d.ts +26 -0
- package/dist/scripts/lib/database/ssl-config.d.ts.map +1 -0
- package/dist/scripts/lib/database/ssl-config.js +47 -0
- package/dist/scripts/lib/database/ssl-config.js.map +1 -0
- package/dist/scripts/lib/errors.d.ts +218 -0
- package/dist/scripts/lib/errors.d.ts.map +1 -0
- package/dist/scripts/lib/errors.js +543 -0
- package/dist/scripts/lib/errors.js.map +1 -0
- package/dist/scripts/lib/exec.d.ts +107 -0
- package/dist/scripts/lib/exec.d.ts.map +1 -0
- package/dist/scripts/lib/exec.js +232 -0
- package/dist/scripts/lib/exec.js.map +1 -0
- package/dist/scripts/lib/index.d.ts +50 -0
- package/dist/scripts/lib/index.d.ts.map +1 -0
- package/dist/scripts/lib/index.js +65 -0
- package/dist/scripts/lib/index.js.map +1 -0
- package/dist/scripts/lib/logger.d.ts +50 -0
- package/dist/scripts/lib/logger.d.ts.map +1 -0
- package/dist/scripts/lib/logger.js +159 -0
- package/dist/scripts/lib/logger.js.map +1 -0
- package/dist/scripts/lib/output.d.ts +149 -0
- package/dist/scripts/lib/output.d.ts.map +1 -0
- package/dist/scripts/lib/output.js +263 -0
- package/dist/scripts/lib/output.js.map +1 -0
- package/dist/scripts/lib/parallel.d.ts +164 -0
- package/dist/scripts/lib/parallel.d.ts.map +1 -0
- package/dist/scripts/lib/parallel.js +355 -0
- package/dist/scripts/lib/parallel.js.map +1 -0
- package/dist/scripts/lib/paths.d.ts +92 -0
- package/dist/scripts/lib/paths.d.ts.map +1 -0
- package/dist/scripts/lib/paths.js +171 -0
- package/dist/scripts/lib/paths.js.map +1 -0
- package/dist/scripts/lib/state/adapters/memory.d.ts +42 -0
- package/dist/scripts/lib/state/adapters/memory.d.ts.map +1 -0
- package/dist/scripts/lib/state/adapters/memory.js +110 -0
- package/dist/scripts/lib/state/adapters/memory.js.map +1 -0
- package/dist/scripts/lib/state/adapters/pglite.d.ts +46 -0
- package/dist/scripts/lib/state/adapters/pglite.d.ts.map +1 -0
- package/dist/scripts/lib/state/adapters/pglite.js +256 -0
- package/dist/scripts/lib/state/adapters/pglite.js.map +1 -0
- package/dist/scripts/lib/state/index.d.ts +16 -0
- package/dist/scripts/lib/state/index.d.ts.map +1 -0
- package/dist/scripts/lib/state/index.js +16 -0
- package/dist/scripts/lib/state/index.js.map +1 -0
- package/dist/scripts/lib/state/types.d.ts +111 -0
- package/dist/scripts/lib/state/types.d.ts.map +1 -0
- package/dist/scripts/lib/state/types.js +8 -0
- package/dist/scripts/lib/state/types.js.map +1 -0
- package/dist/scripts/lib/state/workflow-state.d.ts +110 -0
- package/dist/scripts/lib/state/workflow-state.d.ts.map +1 -0
- package/dist/scripts/lib/state/workflow-state.js +331 -0
- package/dist/scripts/lib/state/workflow-state.js.map +1 -0
- package/dist/scripts/lib/telemetry.d.ts +194 -0
- package/dist/scripts/lib/telemetry.d.ts.map +1 -0
- package/dist/scripts/lib/telemetry.js +394 -0
- package/dist/scripts/lib/telemetry.js.map +1 -0
- package/dist/scripts/lib/utils.d.ts +270 -0
- package/dist/scripts/lib/utils.d.ts.map +1 -0
- package/dist/scripts/lib/utils.js +473 -0
- package/dist/scripts/lib/utils.js.map +1 -0
- package/dist/scripts/lib/validation/database.d.ts +83 -0
- package/dist/scripts/lib/validation/database.d.ts.map +1 -0
- package/dist/scripts/lib/validation/database.js +199 -0
- package/dist/scripts/lib/validation/database.js.map +1 -0
- package/dist/scripts/lib/validation/env.d.ts +80 -0
- package/dist/scripts/lib/validation/env.d.ts.map +1 -0
- package/dist/scripts/lib/validation/env.js +246 -0
- package/dist/scripts/lib/validation/env.js.map +1 -0
- package/dist/scripts/lib/validation/index.d.ts +16 -0
- package/dist/scripts/lib/validation/index.d.ts.map +1 -0
- package/dist/scripts/lib/validation/index.js +16 -0
- package/dist/scripts/lib/validation/index.js.map +1 -0
- package/dist/scripts/lib/validation/post-execution.d.ts +74 -0
- package/dist/scripts/lib/validation/post-execution.d.ts.map +1 -0
- package/dist/scripts/lib/validation/post-execution.js +110 -0
- package/dist/scripts/lib/validation/post-execution.js.map +1 -0
- package/dist/scripts/lib/validation/pre-execution.d.ts +165 -0
- package/dist/scripts/lib/validation/pre-execution.d.ts.map +1 -0
- package/dist/scripts/lib/validation/pre-execution.js +466 -0
- package/dist/scripts/lib/validation/pre-execution.js.map +1 -0
- package/dist/scripts/lib/validators/documentation-validator.d.ts +242 -0
- package/dist/scripts/lib/validators/documentation-validator.d.ts.map +1 -0
- package/dist/scripts/lib/validators/documentation-validator.js +584 -0
- package/dist/scripts/lib/validators/documentation-validator.js.map +1 -0
- package/dist/scripts/lib/validators/index.d.ts +11 -0
- package/dist/scripts/lib/validators/index.d.ts.map +1 -0
- package/dist/scripts/lib/validators/index.js +11 -0
- package/dist/scripts/lib/validators/index.js.map +1 -0
- package/docker-compose.yml +46 -0
- package/docs/INDEX.md +88 -0
- package/docs/README.md +774 -0
- package/docs/SETUP.md +264 -0
- package/docs/servers/code-validator.md +586 -0
- package/eslint.config.js +7 -0
- package/migrations/0001_add_crdt_columns.sql +8 -0
- package/migrations/0001_rollback.sql +6 -0
- package/migrations/005_performance_indexes.sql +190 -0
- package/migrations/backfill_crdt_meta.js +45 -0
- package/package.json +21 -85
- package/src/__tests__/hypervisor.test.ts +212 -0
- package/src/adapters/db.ts +180 -0
- package/src/config/config.json +49 -0
- package/src/config/index.ts +30 -0
- package/src/contracts.ts +221 -0
- package/src/hypervisor.ts +464 -0
- package/src/index.ts +87 -0
- package/src/servers/adapter.ts +643 -0
- package/src/servers/code-validator.ts +188 -0
- package/src/servers/neon.ts +103 -0
- package/src/servers/next-devtools.ts +230 -0
- package/src/servers/playwright.ts +77 -0
- package/src/servers/stripe.ts +99 -0
- package/src/servers/supabase.ts +161 -0
- package/src/servers/vercel.ts +100 -0
- package/src/servers/vultr-test.ts +97 -0
- package/tsconfig.json +12 -0
- package/vitest.config.ts +22 -0
- package/LICENSE +0 -202
- package/dist/index.js +0 -10990
- 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
|
package/src/contracts.ts
ADDED
|
@@ -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
|
+
}
|