/** * Elicitation Store Factory * * Factory functions for creating elicitation stores using @frontmcp/utils storage. * Supports Memory, Redis, and Upstash backends with automatic detection. * * Note: Vercel KV is NOT supported for elicitation because it doesn't support pub/sub * operations which are required for cross-node result routing. * * @module elicitation/store/elicitation-store.factory */ import { type RootStorage, type StorageConfig } from '@frontmcp/utils'; import { type FrontMcpLogger, type RedisOptionsInput, type SqliteOptionsInput } from '../../common'; import { type ElicitationStore } from './elicitation.store'; /** * Options for creating an elicitation store. */ export interface ElicitationStoreOptions { /** * Storage configuration for the elicitation store. * Uses @frontmcp/utils storage configuration format. * * @example Auto-detect * ```typescript * { type: 'auto' } * ``` * * @example Redis * ```typescript * { * type: 'redis', * redis: { url: 'redis://localhost:6379' } * } * ``` * * @example Upstash * ```typescript * { * type: 'upstash', * upstash: { enablePubSub: true } * } * ``` */ storage?: StorageConfig; /** * Redis configuration for distributed deployments. * This is a convenience option that maps to storage.redis. * For new code, prefer using the `storage` option directly. */ redis?: RedisOptionsInput; /** * SQLite configuration for single-node persistent elicitation. * When set, `createSqliteElicitationStore` is used and the `storage` * / `redis` options are ignored. SQLite supports pub/sub via the * SqliteElicitationStore (in-process listeners). */ sqlite?: SqliteOptionsInput; /** * Key prefix for all elicitation keys. * @default 'mcp:elicit:' */ keyPrefix?: string; /** * Logger instance for store operations. */ logger?: FrontMcpLogger; /** * Whether running in Edge runtime (requires distributed storage). * @default false */ isEdgeRuntime?: boolean; /** * Whether to require pub/sub support. * If true, will throw if the storage backend doesn't support pub/sub. * @default true */ requiresPubSub?: boolean; /** * Encryption configuration for elicitation data. * * When enabled, all elicitation data is encrypted using session-derived keys. * This ensures that only requests with the actual sessionId can decrypt the data. * * @example Enable encryption (auto-detect secret from env) * ```typescript * { encryption: { enabled: true } } * ``` * * @example Explicit secret * ```typescript * { encryption: { enabled: true, secret: 'my-secret-key' } } * ``` */ encryption?: { /** * Whether encryption is enabled. * - true: Always encrypt (throws if no secret available) * - false: Never encrypt * - 'auto': Encrypt if secret is available (default) * @default 'auto' */ enabled?: boolean | 'auto'; /** * Server secret for key derivation. * Falls back to MCP_ELICITATION_SECRET, MCP_SESSION_SECRET, or MCP_SERVER_SECRET env vars. */ secret?: string; }; } /** * Result of creating an elicitation store. */ export interface ElicitationStoreResult { /** * The created elicitation store. */ store: ElicitationStore; /** * The type of storage backend used. */ type: 'memory' | 'redis' | 'upstash' | 'sqlite' | 'auto'; /** * The underlying storage instance. * Available for advanced use cases. * * **Undefined for SQLite-backed stores** — `better-sqlite3` doesn't * expose a key-value `StorageAdapter`, so this field is intentionally * absent on the SQLite path. Callers reading `.storage` must guard * for `undefined`. For Redis / Vercel KV / Upstash / memory backends * the adapter is still returned (these all implement the unified * `StorageAdapter` contract). */ storage?: RootStorage; /** * Whether encryption is enabled for the store. */ encrypted: boolean; } /** * Create an elicitation store based on configuration. * * Uses @frontmcp/utils storage abstractions for unified backend support. * * @param options - Store configuration * @returns The created elicitation store with type information * * @example Auto-detect (recommended) * ```typescript * const { store, type } = await createElicitationStore({ * keyPrefix: 'myapp:elicit:', * logger, * }); * ``` * * @example Redis * ```typescript * const { store, type } = await createElicitationStore({ * storage: { * type: 'redis', * redis: { url: 'redis://localhost:6379' }, * }, * logger, * }); * ``` * * @example Memory (development) * ```typescript * const { store, type } = await createElicitationStore({ * storage: { type: 'memory' }, * logger, * }); * ``` * * @throws {ElicitationNotSupportedError} If Vercel KV is configured (no pub/sub support) * @throws {ElicitationNotSupportedError} If running on Edge runtime without distributed storage * @throws {ElicitationNotSupportedError} If pub/sub is required but not supported */ export declare function createElicitationStore(options?: ElicitationStoreOptions): Promise; /** * Create an in-memory elicitation store explicitly. * Use this when you know you want in-memory storage regardless of configuration. * * @param options - Optional configuration * @returns An in-memory elicitation store */ export declare function createMemoryElicitationStore(options?: { keyPrefix?: string; logger?: FrontMcpLogger; encryption?: { enabled?: boolean | 'auto'; secret?: string; }; }): ElicitationStoreResult; /** * Create an elicitation store from an existing storage instance. * Use this when you want to share a storage connection with other systems. * * @param storage - Existing storage instance * @param options - Optional configuration * @returns An elicitation store using the provided storage */ export declare function createElicitationStoreFromStorage(storage: RootStorage, options?: { keyPrefix?: string; logger?: FrontMcpLogger; requiresPubSub?: boolean; encryption?: { enabled?: boolean | 'auto'; secret?: string; }; }): ElicitationStoreResult; /** * Create a SQLite-backed elicitation store for local-only deployments. * Uses EventEmitter for single-process pub/sub (no distributed pub/sub needed). * * @param sqliteConfig - SQLite storage configuration * @param storeOptions - Optional store configuration * @returns A SQLite-backed elicitation store * * @example * ```typescript * const store = createSqliteElicitationStore( * { path: '~/.frontmcp/data/elicitation.sqlite' }, * { logger }, * ); * ``` */ export declare function createSqliteElicitationStore(sqliteConfig: SqliteOptionsInput, storeOptions?: { keyPrefix?: string; logger?: FrontMcpLogger; }): ElicitationStore; //# sourceMappingURL=elicitation-store.factory.d.ts.map