UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

80 lines 9.85 kB
/** * Centralized configuration for handoff payload size limits * * Issue #380 (Post-Review Hardening): Makes handoff size limits configurable * via environment variables. Previously, MAX_RECENT_ENTRIES and MAX_RECENT_DECISIONS * were hardcoded constants in handoff.ts. * * Environment variables follow the pattern: DOLLHOUSE_HANDOFF_* * Values are clamped between safety floors and security ceilings. * * @example * // Override via environment variables (set before server starts) * // DOLLHOUSE_HANDOFF_MAX_RECENT_ENTRIES=50 * // DOLLHOUSE_HANDOFF_MAX_RECENT_DECISIONS=25 * // DOLLHOUSE_HANDOFF_WARN_PAYLOAD_BYTES=512000 */ import { parseEnvInt } from './env-utils.js'; // ==================== HARD LIMITS (Security Ceiling) ==================== /** * Absolute maximum values — cannot be exceeded even with environment variable overrides. * Prevents resource exhaustion via unbounded handoff payloads. */ export const HANDOFF_HARD_LIMITS = { recentEntries: 100, recentDecisions: 50, warnPayloadBytes: 1_048_576, // 1 MB }; // ==================== MIN LIMITS (Safety Floor) ==================== /** * Minimum values — configured values cannot go below these. * Ensures handoff blocks contain enough context to be useful. */ export const HANDOFF_MIN_LIMITS = { recentEntries: 5, recentDecisions: 3, warnPayloadBytes: 1_024, // 1 KB }; // ==================== DEFAULTS ==================== /** * Default values when no environment variable is set. * Matches the original hardcoded constants. */ export const HANDOFF_DEFAULTS = { recentEntries: 20, recentDecisions: 10, warnPayloadBytes: 102_400, // 100 KB }; // ==================== ENVIRONMENT VARIABLE MAPPING ==================== /** * Maps handoff config keys to their environment variable names. * Exported for documentation and testing purposes. */ export const HANDOFF_ENV_VARS = { recentEntries: 'DOLLHOUSE_HANDOFF_MAX_RECENT_ENTRIES', recentDecisions: 'DOLLHOUSE_HANDOFF_MAX_RECENT_DECISIONS', warnPayloadBytes: 'DOLLHOUSE_HANDOFF_WARN_PAYLOAD_BYTES', }; // ==================== PUBLIC API ==================== /** * Get the maximum number of recent entries to include in a handoff payload. * Respects environment variable overrides with validation and clamping. */ export function getHandoffMaxRecentEntries() { return parseEnvInt(HANDOFF_ENV_VARS.recentEntries, HANDOFF_DEFAULTS.recentEntries, HANDOFF_MIN_LIMITS.recentEntries, HANDOFF_HARD_LIMITS.recentEntries, 'Handoff limit'); } /** * Get the maximum number of recent decisions to include in a handoff payload. * Respects environment variable overrides with validation and clamping. */ export function getHandoffMaxRecentDecisions() { return parseEnvInt(HANDOFF_ENV_VARS.recentDecisions, HANDOFF_DEFAULTS.recentDecisions, HANDOFF_MIN_LIMITS.recentDecisions, HANDOFF_HARD_LIMITS.recentDecisions, 'Handoff limit'); } /** * Get the payload size threshold (in bytes) at which a warning is logged. * Respects environment variable overrides with validation and clamping. */ export function getHandoffWarnPayloadBytes() { return parseEnvInt(HANDOFF_ENV_VARS.warnPayloadBytes, HANDOFF_DEFAULTS.warnPayloadBytes, HANDOFF_MIN_LIMITS.warnPayloadBytes, HANDOFF_HARD_LIMITS.warnPayloadBytes, 'Handoff limit'); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZG9mZi1saW1pdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uZmlnL2hhbmRvZmYtbGltaXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3QywyRUFBMkU7QUFDM0U7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUc7SUFDakMsYUFBYSxFQUFFLEdBQUc7SUFDbEIsZUFBZSxFQUFFLEVBQUU7SUFDbkIsZ0JBQWdCLEVBQUUsU0FBUyxFQUFHLE9BQU87Q0FDN0IsQ0FBQztBQUVYLHNFQUFzRTtBQUN0RTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRztJQUNoQyxhQUFhLEVBQUUsQ0FBQztJQUNoQixlQUFlLEVBQUUsQ0FBQztJQUNsQixnQkFBZ0IsRUFBRSxLQUFLLEVBQUcsT0FBTztDQUN6QixDQUFDO0FBRVgscURBQXFEO0FBQ3JEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHO0lBQzlCLGFBQWEsRUFBRSxFQUFFO0lBQ2pCLGVBQWUsRUFBRSxFQUFFO0lBQ25CLGdCQUFnQixFQUFFLE9BQU8sRUFBRyxTQUFTO0NBQzdCLENBQUM7QUFFWCx5RUFBeUU7QUFDekU7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUc7SUFDOUIsYUFBYSxFQUFFLHNDQUFzQztJQUNyRCxlQUFlLEVBQUUsd0NBQXdDO0lBQ3pELGdCQUFnQixFQUFFLHNDQUFzQztDQUNoRCxDQUFDO0FBRVgsdURBQXVEO0FBRXZEOzs7R0FHRztBQUNILE1BQU0sVUFBVSwwQkFBMEI7SUFDeEMsT0FBTyxXQUFXLENBQ2hCLGdCQUFnQixDQUFDLGFBQWEsRUFDOUIsZ0JBQWdCLENBQUMsYUFBYSxFQUM5QixrQkFBa0IsQ0FBQyxhQUFhLEVBQ2hDLG1CQUFtQixDQUFDLGFBQWEsRUFDakMsZUFBZSxDQUNoQixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSw0QkFBNEI7SUFDMUMsT0FBTyxXQUFXLENBQ2hCLGdCQUFnQixDQUFDLGVBQWUsRUFDaEMsZ0JBQWdCLENBQUMsZUFBZSxFQUNoQyxrQkFBa0IsQ0FBQyxlQUFlLEVBQ2xDLG1CQUFtQixDQUFDLGVBQWUsRUFDbkMsZUFBZSxDQUNoQixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSwwQkFBMEI7SUFDeEMsT0FBTyxXQUFXLENBQ2hCLGdCQUFnQixDQUFDLGdCQUFnQixFQUNqQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFDakMsa0JBQWtCLENBQUMsZ0JBQWdCLEVBQ25DLG1CQUFtQixDQUFDLGdCQUFnQixFQUNwQyxlQUFlLENBQ2hCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDZW50cmFsaXplZCBjb25maWd1cmF0aW9uIGZvciBoYW5kb2ZmIHBheWxvYWQgc2l6ZSBsaW1pdHNcbiAqXG4gKiBJc3N1ZSAjMzgwIChQb3N0LVJldmlldyBIYXJkZW5pbmcpOiBNYWtlcyBoYW5kb2ZmIHNpemUgbGltaXRzIGNvbmZpZ3VyYWJsZVxuICogdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcy4gUHJldmlvdXNseSwgTUFYX1JFQ0VOVF9FTlRSSUVTIGFuZCBNQVhfUkVDRU5UX0RFQ0lTSU9OU1xuICogd2VyZSBoYXJkY29kZWQgY29uc3RhbnRzIGluIGhhbmRvZmYudHMuXG4gKlxuICogRW52aXJvbm1lbnQgdmFyaWFibGVzIGZvbGxvdyB0aGUgcGF0dGVybjogRE9MTEhPVVNFX0hBTkRPRkZfKlxuICogVmFsdWVzIGFyZSBjbGFtcGVkIGJldHdlZW4gc2FmZXR5IGZsb29ycyBhbmQgc2VjdXJpdHkgY2VpbGluZ3MuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIE92ZXJyaWRlIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgKHNldCBiZWZvcmUgc2VydmVyIHN0YXJ0cylcbiAqIC8vIERPTExIT1VTRV9IQU5ET0ZGX01BWF9SRUNFTlRfRU5UUklFUz01MFxuICogLy8gRE9MTEhPVVNFX0hBTkRPRkZfTUFYX1JFQ0VOVF9ERUNJU0lPTlM9MjVcbiAqIC8vIERPTExIT1VTRV9IQU5ET0ZGX1dBUk5fUEFZTE9BRF9CWVRFUz01MTIwMDBcbiAqL1xuXG5pbXBvcnQgeyBwYXJzZUVudkludCB9IGZyb20gJy4vZW52LXV0aWxzLmpzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gSEFSRCBMSU1JVFMgKFNlY3VyaXR5IENlaWxpbmcpID09PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIEFic29sdXRlIG1heGltdW0gdmFsdWVzIOKAlCBjYW5ub3QgYmUgZXhjZWVkZWQgZXZlbiB3aXRoIGVudmlyb25tZW50IHZhcmlhYmxlIG92ZXJyaWRlcy5cbiAqIFByZXZlbnRzIHJlc291cmNlIGV4aGF1c3Rpb24gdmlhIHVuYm91bmRlZCBoYW5kb2ZmIHBheWxvYWRzLlxuICovXG5leHBvcnQgY29uc3QgSEFORE9GRl9IQVJEX0xJTUlUUyA9IHtcbiAgcmVjZW50RW50cmllczogMTAwLFxuICByZWNlbnREZWNpc2lvbnM6IDUwLFxuICB3YXJuUGF5bG9hZEJ5dGVzOiAxXzA0OF81NzYsICAvLyAxIE1CXG59IGFzIGNvbnN0O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PSBNSU4gTElNSVRTIChTYWZldHkgRmxvb3IpID09PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIE1pbmltdW0gdmFsdWVzIOKAlCBjb25maWd1cmVkIHZhbHVlcyBjYW5ub3QgZ28gYmVsb3cgdGhlc2UuXG4gKiBFbnN1cmVzIGhhbmRvZmYgYmxvY2tzIGNvbnRhaW4gZW5vdWdoIGNvbnRleHQgdG8gYmUgdXNlZnVsLlxuICovXG5leHBvcnQgY29uc3QgSEFORE9GRl9NSU5fTElNSVRTID0ge1xuICByZWNlbnRFbnRyaWVzOiA1LFxuICByZWNlbnREZWNpc2lvbnM6IDMsXG4gIHdhcm5QYXlsb2FkQnl0ZXM6IDFfMDI0LCAgLy8gMSBLQlxufSBhcyBjb25zdDtcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gREVGQVVMVFMgPT09PT09PT09PT09PT09PT09PT1cbi8qKlxuICogRGVmYXVsdCB2YWx1ZXMgd2hlbiBubyBlbnZpcm9ubWVudCB2YXJpYWJsZSBpcyBzZXQuXG4gKiBNYXRjaGVzIHRoZSBvcmlnaW5hbCBoYXJkY29kZWQgY29uc3RhbnRzLlxuICovXG5leHBvcnQgY29uc3QgSEFORE9GRl9ERUZBVUxUUyA9IHtcbiAgcmVjZW50RW50cmllczogMjAsXG4gIHJlY2VudERlY2lzaW9uczogMTAsXG4gIHdhcm5QYXlsb2FkQnl0ZXM6IDEwMl80MDAsICAvLyAxMDAgS0Jcbn0gYXMgY29uc3Q7XG5cbi8vID09PT09PT09PT09PT09PT09PT09IEVOVklST05NRU5UIFZBUklBQkxFIE1BUFBJTkcgPT09PT09PT09PT09PT09PT09PT1cbi8qKlxuICogTWFwcyBoYW5kb2ZmIGNvbmZpZyBrZXlzIHRvIHRoZWlyIGVudmlyb25tZW50IHZhcmlhYmxlIG5hbWVzLlxuICogRXhwb3J0ZWQgZm9yIGRvY3VtZW50YXRpb24gYW5kIHRlc3RpbmcgcHVycG9zZXMuXG4gKi9cbmV4cG9ydCBjb25zdCBIQU5ET0ZGX0VOVl9WQVJTID0ge1xuICByZWNlbnRFbnRyaWVzOiAnRE9MTEhPVVNFX0hBTkRPRkZfTUFYX1JFQ0VOVF9FTlRSSUVTJyxcbiAgcmVjZW50RGVjaXNpb25zOiAnRE9MTEhPVVNFX0hBTkRPRkZfTUFYX1JFQ0VOVF9ERUNJU0lPTlMnLFxuICB3YXJuUGF5bG9hZEJ5dGVzOiAnRE9MTEhPVVNFX0hBTkRPRkZfV0FSTl9QQVlMT0FEX0JZVEVTJyxcbn0gYXMgY29uc3Q7XG5cbi8vID09PT09PT09PT09PT09PT09PT09IFBVQkxJQyBBUEkgPT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZXQgdGhlIG1heGltdW0gbnVtYmVyIG9mIHJlY2VudCBlbnRyaWVzIHRvIGluY2x1ZGUgaW4gYSBoYW5kb2ZmIHBheWxvYWQuXG4gKiBSZXNwZWN0cyBlbnZpcm9ubWVudCB2YXJpYWJsZSBvdmVycmlkZXMgd2l0aCB2YWxpZGF0aW9uIGFuZCBjbGFtcGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEhhbmRvZmZNYXhSZWNlbnRFbnRyaWVzKCk6IG51bWJlciB7XG4gIHJldHVybiBwYXJzZUVudkludChcbiAgICBIQU5ET0ZGX0VOVl9WQVJTLnJlY2VudEVudHJpZXMsXG4gICAgSEFORE9GRl9ERUZBVUxUUy5yZWNlbnRFbnRyaWVzLFxuICAgIEhBTkRPRkZfTUlOX0xJTUlUUy5yZWNlbnRFbnRyaWVzLFxuICAgIEhBTkRPRkZfSEFSRF9MSU1JVFMucmVjZW50RW50cmllcyxcbiAgICAnSGFuZG9mZiBsaW1pdCdcbiAgKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG1heGltdW0gbnVtYmVyIG9mIHJlY2VudCBkZWNpc2lvbnMgdG8gaW5jbHVkZSBpbiBhIGhhbmRvZmYgcGF5bG9hZC5cbiAqIFJlc3BlY3RzIGVudmlyb25tZW50IHZhcmlhYmxlIG92ZXJyaWRlcyB3aXRoIHZhbGlkYXRpb24gYW5kIGNsYW1waW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SGFuZG9mZk1heFJlY2VudERlY2lzaW9ucygpOiBudW1iZXIge1xuICByZXR1cm4gcGFyc2VFbnZJbnQoXG4gICAgSEFORE9GRl9FTlZfVkFSUy5yZWNlbnREZWNpc2lvbnMsXG4gICAgSEFORE9GRl9ERUZBVUxUUy5yZWNlbnREZWNpc2lvbnMsXG4gICAgSEFORE9GRl9NSU5fTElNSVRTLnJlY2VudERlY2lzaW9ucyxcbiAgICBIQU5ET0ZGX0hBUkRfTElNSVRTLnJlY2VudERlY2lzaW9ucyxcbiAgICAnSGFuZG9mZiBsaW1pdCdcbiAgKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHBheWxvYWQgc2l6ZSB0aHJlc2hvbGQgKGluIGJ5dGVzKSBhdCB3aGljaCBhIHdhcm5pbmcgaXMgbG9nZ2VkLlxuICogUmVzcGVjdHMgZW52aXJvbm1lbnQgdmFyaWFibGUgb3ZlcnJpZGVzIHdpdGggdmFsaWRhdGlvbiBhbmQgY2xhbXBpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRIYW5kb2ZmV2FyblBheWxvYWRCeXRlcygpOiBudW1iZXIge1xuICByZXR1cm4gcGFyc2VFbnZJbnQoXG4gICAgSEFORE9GRl9FTlZfVkFSUy53YXJuUGF5bG9hZEJ5dGVzLFxuICAgIEhBTkRPRkZfREVGQVVMVFMud2FyblBheWxvYWRCeXRlcyxcbiAgICBIQU5ET0ZGX01JTl9MSU1JVFMud2FyblBheWxvYWRCeXRlcyxcbiAgICBIQU5ET0ZGX0hBUkRfTElNSVRTLndhcm5QYXlsb2FkQnl0ZXMsXG4gICAgJ0hhbmRvZmYgbGltaXQnXG4gICk7XG59XG4iXX0=