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.

99 lines 11.5 kB
/** * Centralized configuration for active element limits * * Issue #83 (Phase 1): Makes active element limits configurable via environment variables. * Previously, each manager had hardcoded MAX_ACTIVE_* and ACTIVE_SET_CLEANUP_THRESHOLD constants. * * Environment variables follow the pattern: DOLLHOUSE_MAX_ACTIVE_{TYPE} * Values are clamped between safety floors and security ceilings. * * @example * // Override via environment variables (set before server starts) * // DOLLHOUSE_MAX_ACTIVE_SKILLS=300 * // DOLLHOUSE_MAX_ACTIVE_AGENTS=150 * // DOLLHOUSE_MAX_ACTIVE_MEMORIES=200 * // DOLLHOUSE_MAX_ACTIVE_ENSEMBLES=75 * // DOLLHOUSE_MAX_ACTIVE_PERSONAS=50 */ import { parseEnvInt } from './env-utils.js'; // ==================== HARD LIMITS (Security Ceiling) ==================== /** * Absolute maximum values — cannot be exceeded even with environment variable overrides. * Prevents resource exhaustion and DoS via unbounded active sets. */ export const ACTIVE_ELEMENT_HARD_LIMITS = { skills: 1000, agents: 500, memories: 500, ensembles: 200, personas: 100 }; // ==================== MIN LIMITS (Safety Floor) ==================== /** * Minimum values — configured values cannot go below these. * Ensures basic functionality is always available. */ export const ACTIVE_ELEMENT_MIN_LIMITS = { skills: 5, agents: 5, memories: 5, ensembles: 2, personas: 2 }; // ==================== DEFAULTS ==================== /** * Default max active limits when no environment variable is set. * Increased from original hardcoded values for better out-of-box experience. */ export const ACTIVE_ELEMENT_DEFAULTS = { skills: 200, // was 100 agents: 100, // was 50 memories: 100, // was 30 ensembles: 50, // was 20 personas: 20 // new (previously unlimited) }; // ==================== ENVIRONMENT VARIABLE MAPPING ==================== /** * Maps element types to their environment variable names. * Exported for documentation and testing purposes. */ export const ACTIVE_LIMIT_ENV_VARS = { skills: 'DOLLHOUSE_MAX_ACTIVE_SKILLS', agents: 'DOLLHOUSE_MAX_ACTIVE_AGENTS', memories: 'DOLLHOUSE_MAX_ACTIVE_MEMORIES', ensembles: 'DOLLHOUSE_MAX_ACTIVE_ENSEMBLES', personas: 'DOLLHOUSE_MAX_ACTIVE_PERSONAS' }; // ==================== INTERNAL CONSTANTS ==================== /** Ratio of max at which stale-reference cleanup begins (90% of max) */ const CLEANUP_THRESHOLD_RATIO = 0.9; // ==================== PUBLIC API ==================== /** * Get the maximum active element limit for a given element type. * Respects environment variable overrides with validation and clamping. * * @param type - Element type * @returns Maximum active elements allowed */ export function getMaxActiveLimit(type) { const envVar = ACTIVE_LIMIT_ENV_VARS[type]; const defaultValue = ACTIVE_ELEMENT_DEFAULTS[type]; const min = ACTIVE_ELEMENT_MIN_LIMITS[type]; const max = ACTIVE_ELEMENT_HARD_LIMITS[type]; return parseEnvInt(envVar, defaultValue, min, max, 'Active element limit'); } /** * Get the full active element limit configuration for a given element type. * Returns both max limit and cleanup threshold (floor(max * 0.9)). * * @param type - Element type * @returns Configuration with max and cleanupThreshold */ export function getActiveElementLimitConfig(type) { const max = getMaxActiveLimit(type); return { max, cleanupThreshold: Math.floor(max * CLEANUP_THRESHOLD_RATIO) }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aXZlLWVsZW1lbnQtbGltaXRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy9hY3RpdmUtZWxlbWVudC1saW1pdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFlN0MsMkVBQTJFO0FBQzNFOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUEyQztJQUNoRixNQUFNLEVBQUUsSUFBSTtJQUNaLE1BQU0sRUFBRSxHQUFHO0lBQ1gsUUFBUSxFQUFFLEdBQUc7SUFDYixTQUFTLEVBQUUsR0FBRztJQUNkLFFBQVEsRUFBRSxHQUFHO0NBQ2QsQ0FBQztBQUVGLHNFQUFzRTtBQUN0RTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBMkM7SUFDL0UsTUFBTSxFQUFFLENBQUM7SUFDVCxNQUFNLEVBQUUsQ0FBQztJQUNULFFBQVEsRUFBRSxDQUFDO0lBQ1gsU0FBUyxFQUFFLENBQUM7SUFDWixRQUFRLEVBQUUsQ0FBQztDQUNaLENBQUM7QUFFRixxREFBcUQ7QUFDckQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQTJDO0lBQzdFLE1BQU0sRUFBRSxHQUFHLEVBQUssVUFBVTtJQUMxQixNQUFNLEVBQUUsR0FBRyxFQUFLLFNBQVM7SUFDekIsUUFBUSxFQUFFLEdBQUcsRUFBRyxTQUFTO0lBQ3pCLFNBQVMsRUFBRSxFQUFFLEVBQUcsU0FBUztJQUN6QixRQUFRLEVBQUUsRUFBRSxDQUFJLDZCQUE2QjtDQUM5QyxDQUFDO0FBRUYseUVBQXlFO0FBQ3pFOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUEyQztJQUMzRSxNQUFNLEVBQUUsNkJBQTZCO0lBQ3JDLE1BQU0sRUFBRSw2QkFBNkI7SUFDckMsUUFBUSxFQUFFLCtCQUErQjtJQUN6QyxTQUFTLEVBQUUsZ0NBQWdDO0lBQzNDLFFBQVEsRUFBRSwrQkFBK0I7Q0FDMUMsQ0FBQztBQUVGLCtEQUErRDtBQUUvRCx3RUFBd0U7QUFDeEUsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUM7QUFFcEMsdURBQXVEO0FBRXZEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxJQUE0QjtJQUM1RCxNQUFNLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxNQUFNLFlBQVksR0FBRyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRCxNQUFNLEdBQUcsR0FBRyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QyxNQUFNLEdBQUcsR0FBRywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU3QyxPQUFPLFdBQVcsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztBQUM3RSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLDJCQUEyQixDQUFDLElBQTRCO0lBQ3RFLE1BQU0sR0FBRyxHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLE9BQU87UUFDTCxHQUFHO1FBQ0gsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsdUJBQXVCLENBQUM7S0FDNUQsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENlbnRyYWxpemVkIGNvbmZpZ3VyYXRpb24gZm9yIGFjdGl2ZSBlbGVtZW50IGxpbWl0c1xuICpcbiAqIElzc3VlICM4MyAoUGhhc2UgMSk6IE1ha2VzIGFjdGl2ZSBlbGVtZW50IGxpbWl0cyBjb25maWd1cmFibGUgdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAqIFByZXZpb3VzbHksIGVhY2ggbWFuYWdlciBoYWQgaGFyZGNvZGVkIE1BWF9BQ1RJVkVfKiBhbmQgQUNUSVZFX1NFVF9DTEVBTlVQX1RIUkVTSE9MRCBjb25zdGFudHMuXG4gKlxuICogRW52aXJvbm1lbnQgdmFyaWFibGVzIGZvbGxvdyB0aGUgcGF0dGVybjogRE9MTEhPVVNFX01BWF9BQ1RJVkVfe1RZUEV9XG4gKiBWYWx1ZXMgYXJlIGNsYW1wZWQgYmV0d2VlbiBzYWZldHkgZmxvb3JzIGFuZCBzZWN1cml0eSBjZWlsaW5ncy5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gT3ZlcnJpZGUgdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyAoc2V0IGJlZm9yZSBzZXJ2ZXIgc3RhcnRzKVxuICogLy8gRE9MTEhPVVNFX01BWF9BQ1RJVkVfU0tJTExTPTMwMFxuICogLy8gRE9MTEhPVVNFX01BWF9BQ1RJVkVfQUdFTlRTPTE1MFxuICogLy8gRE9MTEhPVVNFX01BWF9BQ1RJVkVfTUVNT1JJRVM9MjAwXG4gKiAvLyBET0xMSE9VU0VfTUFYX0FDVElWRV9FTlNFTUJMRVM9NzVcbiAqIC8vIERPTExIT1VTRV9NQVhfQUNUSVZFX1BFUlNPTkFTPTUwXG4gKi9cblxuaW1wb3J0IHsgcGFyc2VFbnZJbnQgfSBmcm9tICcuL2Vudi11dGlscy5qcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09IFRZUEVTID09PT09PT09PT09PT09PT09PT09XG5cbi8qKiBFbGVtZW50IHR5cGVzIHRoYXQgc3VwcG9ydCBhY3RpdmUgZWxlbWVudCBsaW1pdHMgKi9cbmV4cG9ydCB0eXBlIEFjdGl2ZUxpbWl0RWxlbWVudFR5cGUgPSAnc2tpbGxzJyB8ICdhZ2VudHMnIHwgJ21lbW9yaWVzJyB8ICdlbnNlbWJsZXMnIHwgJ3BlcnNvbmFzJztcblxuLyoqIENvbmZpZ3VyYXRpb24gZm9yIGEgc2luZ2xlIGVsZW1lbnQgdHlwZSdzIGFjdGl2ZSBsaW1pdHMgKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aXZlRWxlbWVudExpbWl0Q29uZmlnIHtcbiAgLyoqIE1heGltdW0gbnVtYmVyIG9mIGFjdGl2ZSBlbGVtZW50cyBiZWZvcmUgd2FybmluZy9jbGVhbnVwIHRyaWdnZXJzICovXG4gIG1heDogbnVtYmVyO1xuICAvKiogVGhyZXNob2xkIGF0IHdoaWNoIGNsZWFudXAgb2Ygc3RhbGUgcmVmZXJlbmNlcyBiZWdpbnMgKHR5cGljYWxseSBmbG9vcihtYXggKiAwLjkpKSAqL1xuICBjbGVhbnVwVGhyZXNob2xkOiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09IEhBUkQgTElNSVRTIChTZWN1cml0eSBDZWlsaW5nKSA9PT09PT09PT09PT09PT09PT09PVxuLyoqXG4gKiBBYnNvbHV0ZSBtYXhpbXVtIHZhbHVlcyDigJQgY2Fubm90IGJlIGV4Y2VlZGVkIGV2ZW4gd2l0aCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvdmVycmlkZXMuXG4gKiBQcmV2ZW50cyByZXNvdXJjZSBleGhhdXN0aW9uIGFuZCBEb1MgdmlhIHVuYm91bmRlZCBhY3RpdmUgc2V0cy5cbiAqL1xuZXhwb3J0IGNvbnN0IEFDVElWRV9FTEVNRU5UX0hBUkRfTElNSVRTOiBSZWNvcmQ8QWN0aXZlTGltaXRFbGVtZW50VHlwZSwgbnVtYmVyPiA9IHtcbiAgc2tpbGxzOiAxMDAwLFxuICBhZ2VudHM6IDUwMCxcbiAgbWVtb3JpZXM6IDUwMCxcbiAgZW5zZW1ibGVzOiAyMDAsXG4gIHBlcnNvbmFzOiAxMDBcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09IE1JTiBMSU1JVFMgKFNhZmV0eSBGbG9vcikgPT09PT09PT09PT09PT09PT09PT1cbi8qKlxuICogTWluaW11bSB2YWx1ZXMg4oCUIGNvbmZpZ3VyZWQgdmFsdWVzIGNhbm5vdCBnbyBiZWxvdyB0aGVzZS5cbiAqIEVuc3VyZXMgYmFzaWMgZnVuY3Rpb25hbGl0eSBpcyBhbHdheXMgYXZhaWxhYmxlLlxuICovXG5leHBvcnQgY29uc3QgQUNUSVZFX0VMRU1FTlRfTUlOX0xJTUlUUzogUmVjb3JkPEFjdGl2ZUxpbWl0RWxlbWVudFR5cGUsIG51bWJlcj4gPSB7XG4gIHNraWxsczogNSxcbiAgYWdlbnRzOiA1LFxuICBtZW1vcmllczogNSxcbiAgZW5zZW1ibGVzOiAyLFxuICBwZXJzb25hczogMlxufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gREVGQVVMVFMgPT09PT09PT09PT09PT09PT09PT1cbi8qKlxuICogRGVmYXVsdCBtYXggYWN0aXZlIGxpbWl0cyB3aGVuIG5vIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIHNldC5cbiAqIEluY3JlYXNlZCBmcm9tIG9yaWdpbmFsIGhhcmRjb2RlZCB2YWx1ZXMgZm9yIGJldHRlciBvdXQtb2YtYm94IGV4cGVyaWVuY2UuXG4gKi9cbmV4cG9ydCBjb25zdCBBQ1RJVkVfRUxFTUVOVF9ERUZBVUxUUzogUmVjb3JkPEFjdGl2ZUxpbWl0RWxlbWVudFR5cGUsIG51bWJlcj4gPSB7XG4gIHNraWxsczogMjAwLCAgICAvLyB3YXMgMTAwXG4gIGFnZW50czogMTAwLCAgICAvLyB3YXMgNTBcbiAgbWVtb3JpZXM6IDEwMCwgIC8vIHdhcyAzMFxuICBlbnNlbWJsZXM6IDUwLCAgLy8gd2FzIDIwXG4gIHBlcnNvbmFzOiAyMCAgICAvLyBuZXcgKHByZXZpb3VzbHkgdW5saW1pdGVkKVxufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gRU5WSVJPTk1FTlQgVkFSSUFCTEUgTUFQUElORyA9PT09PT09PT09PT09PT09PT09PVxuLyoqXG4gKiBNYXBzIGVsZW1lbnQgdHlwZXMgdG8gdGhlaXIgZW52aXJvbm1lbnQgdmFyaWFibGUgbmFtZXMuXG4gKiBFeHBvcnRlZCBmb3IgZG9jdW1lbnRhdGlvbiBhbmQgdGVzdGluZyBwdXJwb3Nlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IEFDVElWRV9MSU1JVF9FTlZfVkFSUzogUmVjb3JkPEFjdGl2ZUxpbWl0RWxlbWVudFR5cGUsIHN0cmluZz4gPSB7XG4gIHNraWxsczogJ0RPTExIT1VTRV9NQVhfQUNUSVZFX1NLSUxMUycsXG4gIGFnZW50czogJ0RPTExIT1VTRV9NQVhfQUNUSVZFX0FHRU5UUycsXG4gIG1lbW9yaWVzOiAnRE9MTEhPVVNFX01BWF9BQ1RJVkVfTUVNT1JJRVMnLFxuICBlbnNlbWJsZXM6ICdET0xMSE9VU0VfTUFYX0FDVElWRV9FTlNFTUJMRVMnLFxuICBwZXJzb25hczogJ0RPTExIT1VTRV9NQVhfQUNUSVZFX1BFUlNPTkFTJ1xufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gSU5URVJOQUwgQ09OU1RBTlRTID09PT09PT09PT09PT09PT09PT09XG5cbi8qKiBSYXRpbyBvZiBtYXggYXQgd2hpY2ggc3RhbGUtcmVmZXJlbmNlIGNsZWFudXAgYmVnaW5zICg5MCUgb2YgbWF4KSAqL1xuY29uc3QgQ0xFQU5VUF9USFJFU0hPTERfUkFUSU8gPSAwLjk7XG5cbi8vID09PT09PT09PT09PT09PT09PT09IFBVQkxJQyBBUEkgPT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZXQgdGhlIG1heGltdW0gYWN0aXZlIGVsZW1lbnQgbGltaXQgZm9yIGEgZ2l2ZW4gZWxlbWVudCB0eXBlLlxuICogUmVzcGVjdHMgZW52aXJvbm1lbnQgdmFyaWFibGUgb3ZlcnJpZGVzIHdpdGggdmFsaWRhdGlvbiBhbmQgY2xhbXBpbmcuXG4gKlxuICogQHBhcmFtIHR5cGUgLSBFbGVtZW50IHR5cGVcbiAqIEByZXR1cm5zIE1heGltdW0gYWN0aXZlIGVsZW1lbnRzIGFsbG93ZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1heEFjdGl2ZUxpbWl0KHR5cGU6IEFjdGl2ZUxpbWl0RWxlbWVudFR5cGUpOiBudW1iZXIge1xuICBjb25zdCBlbnZWYXIgPSBBQ1RJVkVfTElNSVRfRU5WX1ZBUlNbdHlwZV07XG4gIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IEFDVElWRV9FTEVNRU5UX0RFRkFVTFRTW3R5cGVdO1xuICBjb25zdCBtaW4gPSBBQ1RJVkVfRUxFTUVOVF9NSU5fTElNSVRTW3R5cGVdO1xuICBjb25zdCBtYXggPSBBQ1RJVkVfRUxFTUVOVF9IQVJEX0xJTUlUU1t0eXBlXTtcblxuICByZXR1cm4gcGFyc2VFbnZJbnQoZW52VmFyLCBkZWZhdWx0VmFsdWUsIG1pbiwgbWF4LCAnQWN0aXZlIGVsZW1lbnQgbGltaXQnKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGZ1bGwgYWN0aXZlIGVsZW1lbnQgbGltaXQgY29uZmlndXJhdGlvbiBmb3IgYSBnaXZlbiBlbGVtZW50IHR5cGUuXG4gKiBSZXR1cm5zIGJvdGggbWF4IGxpbWl0IGFuZCBjbGVhbnVwIHRocmVzaG9sZCAoZmxvb3IobWF4ICogMC45KSkuXG4gKlxuICogQHBhcmFtIHR5cGUgLSBFbGVtZW50IHR5cGVcbiAqIEByZXR1cm5zIENvbmZpZ3VyYXRpb24gd2l0aCBtYXggYW5kIGNsZWFudXBUaHJlc2hvbGRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFjdGl2ZUVsZW1lbnRMaW1pdENvbmZpZyh0eXBlOiBBY3RpdmVMaW1pdEVsZW1lbnRUeXBlKTogQWN0aXZlRWxlbWVudExpbWl0Q29uZmlnIHtcbiAgY29uc3QgbWF4ID0gZ2V0TWF4QWN0aXZlTGltaXQodHlwZSk7XG4gIHJldHVybiB7XG4gICAgbWF4LFxuICAgIGNsZWFudXBUaHJlc2hvbGQ6IE1hdGguZmxvb3IobWF4ICogQ0xFQU5VUF9USFJFU0hPTERfUkFUSU8pXG4gIH07XG59XG4iXX0=