UNPKG

@iflow-mcp/ansvar-systems-german-law-mcp

Version:

German legal research MCP server with statutes, case law, and preparatory works from gesetze-im-internet.de

90 lines (89 loc) • 3.39 kB
/** * Runtime capability detection for the German Law MCP server. * * The server inspects which SQLite tables are present on startup and * exposes a Set<Capability> so that tool handlers can gate features * (or return an upgrade prompt) without hard-coding tier logic. */ // --------------------------------------------------------------------------- // Table → Capability mapping // --------------------------------------------------------------------------- const CAPABILITY_TABLES = { core_legislation: 'law_documents', basic_case_law: 'case_law_documents', eu_references: 'eu_references', expanded_case_law: 'case_law_documents_full', full_preparatory_works: 'preparatory_works_full', agency_guidance: 'agency_guidance', }; const PROFESSIONAL_CAPABILITIES = new Set([ 'expanded_case_law', 'full_preparatory_works', 'agency_guidance', ]); // --------------------------------------------------------------------------- // Public API // --------------------------------------------------------------------------- /** Detect which capabilities the current database supports. */ export function detectCapabilities(db) { const caps = new Set(); for (const [capability, table] of Object.entries(CAPABILITY_TABLES)) { if (tableExists(db, table)) { caps.add(capability); } } return caps; } /** Read db_metadata key-value pairs. Returns sensible defaults when missing. */ export function readDbMetadata(db) { const defaults = { tier: 'unknown', schema_version: '1', built_at: 'unknown', builder: 'unknown', }; if (!tableExists(db, 'db_metadata')) { return defaults; } try { const rows = db .prepare('SELECT key, value FROM db_metadata') .all(); const map = new Map(rows.map((r) => [r.key, r.value])); const rawTier = map.get('tier') ?? 'unknown'; const tier = rawTier === 'free' || rawTier === 'professional' ? rawTier : 'unknown'; return { tier, schema_version: map.get('schema_version') ?? defaults.schema_version, built_at: map.get('built_at') ?? defaults.built_at, builder: map.get('builder') ?? defaults.builder, }; } catch { return defaults; } } /** Check whether a capability belongs to the paid (professional) tier. */ export function isProfessionalCapability(cap) { return PROFESSIONAL_CAPABILITIES.has(cap); } /** Human-readable upgrade prompt for gated features. */ export function upgradeMessage(feature) { return (`${feature} is not available in this free community instance. ` + `The full case law and preparatory works databases are too large to serve from a free hosted endpoint. ` + `These datasets are included when Ansvar delivers consulting services, and may become available as a separate paid service in the future.`); } // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- function tableExists(db, name) { try { const row = db .prepare("SELECT 1 AS ok FROM sqlite_master WHERE type IN ('table','view') AND name = ?") .get(name); return Boolean(row?.ok); } catch { return false; } }