UNPKG

@inso_web/els-mcp

Version:

MCP-сервер поверх INSO Error Logs Service. Read-only tools (search, analytics, fingerprinting, correlations) для подключения Claude Desktop/Code и ChatGPT к логам ошибок. Streamable HTTP transport + stdio для npx-запуска.

90 lines 3.58 kB
import { createHash } from 'node:crypto'; /** * Cache TTL policies per "tool class". * * Источник: `todo/error-logs-service/mcp/05-high-load.md` § 2.1. * * Class имена используются: * - как `tool_class` label в Prometheus метриках (`mcp_cache_hit_ratio`); * - как первая часть Redis key namespace (`mcp:cache:{class}:...`). * * Изменения дефолтов делайте здесь, не в `cachedElsClient.ts` — chair pattern. * * Значения можно override через ENV `MCP_CACHE_TTL_OVERRIDE_{CLASS}=secs` * (см. `src/config.ts`). */ export const CACHE_POLICIES = { log_details: 3600, traffic_long: 300, traffic_short: 60, top_messages: 120, stats_breakdown: 120, search_recent: 15, list_apps: 30, heatmap: 300, histogram: 60, baseline: 300, version_timeline: 300, grouped_errors: 120, }; /** * Объединяет дефолтные политики с user overrides из конфига. */ export function resolvePolicies(overrides = {}) { const result = { ...CACHE_POLICIES }; for (const [k, v] of Object.entries(overrides)) { if (typeof v === 'number' && Number.isFinite(v) && v >= 0 && k in result) { result[k] = v; } } return result; } /** * Стабильный sha256 hash от объекта параметров (отсортированные ключи). * * НЕ криптографически стойкий — это просто детерминированный fingerprint. * Используется для построения cache key (paramsHash). * * Возвращает base64url-encoded 16 chars. */ export function paramsHash(params) { const keys = Object.keys(params).sort(); const canon = JSON.stringify(params, keys); return createHash('sha256').update(canon).digest('base64url').slice(0, 16); } /** * Tenant-isolated cache key builder. * * **Обязательная** проверка: в key всегда присутствует tenant-идентификатор * (`appSlug` или `keyPrefix`). Иначе — `Error`. * * Формат: * `mcp:cache:{scope}:{tenant}:{...parts}` * * Это **единственный** разрешённый путь создания cache key в проекте. * * @throws Error если tenant=null AND keyPrefix=empty (cross-tenant leak guard) */ export function tenantKey(scope, appSlug, parts, fallbackKeyPrefix) { // Защита от пустого scope if (!scope || /[:\s]/.test(scope)) { throw new Error(`Invalid cache scope: "${scope}"`); } const tenant = (appSlug && appSlug.trim().length > 0 && appSlug) || (fallbackKeyPrefix && fallbackKeyPrefix.trim().length > 0 && `k:${fallbackKeyPrefix}`) || null; if (!tenant) { // Tenant-isolation violation — это критический баг, см. § 2.1 spec. throw new Error('tenantKey() called without appSlug AND without keyPrefix — refusing to build cross-tenant cache key'); } const safeParts = parts.map((p) => sanitizeKeyPart(String(p))); return `mcp:cache:${scope}:${tenant}:${safeParts.join(':')}`; } /** * Удаляет небезопасные для Redis key символы (whitespace, разделители). * Заменяет на '_'. Для traceId / hash — операция no-op. */ function sanitizeKeyPart(s) { return s.replace(/[\s:{}\[\]]/g, '_').slice(0, 256); } //# sourceMappingURL=policies.js.map