@jacobmolz/mcpguard 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/config/schema.ts","../src/errors.ts","../src/config/fetcher.ts","../src/config/merger.ts","../src/config/loader.ts","../src/cli.ts","../src/daemon/index.ts","../src/identity/daemon-key.ts","../src/storage/sqlite.ts","../src/storage/migrations.ts","../src/daemon/socket-server.ts","../src/identity/os-identity.ts","../src/proxy/mcp-client.ts","../src/daemon/server-manager.ts","../src/proxy/mcp-server.ts","../src/daemon/shutdown.ts","../src/logger.ts","../src/interceptors/pipeline.ts","../src/interceptors/auth.ts","../src/identity/token-validator.ts","../src/identity/roles.ts","../src/interceptors/effective-policy.ts","../src/interceptors/rate-limit.ts","../src/interceptors/permissions.ts","../src/interceptors/sampling-guard.ts","../src/pii/redactor.ts","../src/interceptors/pii-detect.ts","../src/pii/regex-detector.ts","../src/pii/registry.ts","../src/storage/rate-limit-store.ts","../src/audit/store.ts","../src/audit/stdout-logger.ts","../src/audit/tap.ts","../src/proxy/capability-filter.ts","../src/config/watcher.ts","../src/dashboard/server.ts","../src/dashboard/health.ts","../src/bridge/index.ts","../src/bridge/auth.ts","../src/daemon/auto-start.ts","../src/identity/token-store.ts","../src/audit/query.ts","../src/identity/oauth-flow.ts","../src/cli/init.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport const DEFAULT_HOME = join(homedir(), '.config', 'mcp-guard');\nexport const DEFAULT_SOCKET_PATH = join(DEFAULT_HOME, 'daemon.sock');\nexport const DEFAULT_PID_FILE = join(DEFAULT_HOME, 'daemon.pid');\nexport const DEFAULT_DAEMON_KEY_PATH = join(DEFAULT_HOME, 'daemon.key');\nexport const DEFAULT_DB_PATH = join(DEFAULT_HOME, 'mcp-guard.db');\nexport const DEFAULT_CONFIG_PATH = 'mcp-guard.yaml';\nexport const DEFAULT_DASHBOARD_PORT = 9777;\nexport const DEFAULT_SHUTDOWN_TIMEOUT = 30_000;\nexport const DAEMON_KEY_BYTES = 32;\nexport const AUTH_TIMEOUT = 5_000;\nexport const MAX_MESSAGE_SIZE = 4 * 1024 * 1024; // 4MB\nexport const DEFAULT_EXTENDS_CACHE_DIR = 'extends-cache';\nexport const EXTENDS_FETCH_TIMEOUT = 10_000; // 10s\nexport const CONFIG_RELOAD_DEBOUNCE = 250; // 250ms\n\n// OAuth\nexport const OAUTH_TOKEN_DIR = 'oauth-tokens';\nexport const OAUTH_TOKEN_FILE_MODE = 0o600;\nexport const OAUTH_CALLBACK_PORT = 8399;\nexport const OAUTH_CALLBACK_TIMEOUT = 120_000; // 2 min for user to complete browser auth\n","import { z } from 'zod';\nimport {\n DEFAULT_SOCKET_PATH,\n DEFAULT_HOME,\n DEFAULT_DASHBOARD_PORT,\n} from '../constants.js';\n\nexport const permissionsSchema = z.object({\n allowed_tools: z.array(z.string()).optional(),\n denied_tools: z.array(z.string()).default([]),\n allowed_resources: z.array(z.string()).optional(),\n denied_resources: z.array(z.string()).default([]),\n}).default({});\n\nexport const rateLimitSchema = z.object({\n requests_per_minute: z.number().min(1).optional(),\n requests_per_hour: z.number().min(1).optional(),\n tool_limits: z.record(z.string(), z.object({\n requests_per_minute: z.number().min(1).optional(),\n })).default({}),\n}).default({});\n\nexport const policySchema = z.object({\n permissions: permissionsSchema,\n rate_limit: rateLimitSchema,\n sampling: z.object({\n enabled: z.boolean().default(false),\n max_tokens: z.number().min(1).optional(),\n rate_limit: z.number().min(1).optional(),\n audit: z.enum(['basic', 'verbose']).default('basic'),\n }).default({}),\n locked: z.boolean().default(false),\n}).default({});\n\nexport const serverSchema = z.object({\n command: z.string().optional(),\n args: z.array(z.string()).default([]),\n env: z.record(z.string()).default({}),\n url: z.string().url().optional(),\n transport: z.enum(['stdio', 'sse', 'streamable-http']).default('stdio'),\n /** Bearer token for authenticating MCP-Guard to the upstream HTTP server.\n * Use env var interpolation for security: upstream_auth_token: \"${MCP_AUTH_TOKEN}\" */\n upstream_auth_token: z.string().optional(),\n policy: policySchema,\n});\n\nexport const daemonSchema = z.object({\n socket_path: z.string().default(DEFAULT_SOCKET_PATH),\n home: z.string().default(DEFAULT_HOME),\n shutdown_timeout: z.number().min(1).default(30),\n log_level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\n dashboard_port: z.number().min(0).max(65535).default(DEFAULT_DASHBOARD_PORT),\n encryption: z.object({\n enabled: z.boolean().default(false),\n }).default({}),\n});\n\nexport const claimsToRolesSchema = z.object({\n claim_name: z.string().default('roles'),\n mapping: z.record(z.string(), z.array(z.string())).default({}),\n}).default({});\n\nexport const oauthSchema = z.object({\n issuer: z.string().url(),\n jwks_uri: z.string().url().optional(),\n audience: z.string().optional(),\n client_id: z.string(),\n client_secret: z.string().optional(),\n scopes: z.array(z.string()).default(['openid', 'profile']),\n claims_to_roles: claimsToRolesSchema,\n clock_tolerance_seconds: z.number().min(0).max(300).default(30),\n});\n\nexport const authSchema = z.object({\n mode: z.enum(['os', 'api_key', 'oauth']).default('os'),\n api_keys: z.record(z.string(), z.object({\n roles: z.array(z.string()).default(['default']),\n })).default({}),\n oauth: oauthSchema.optional(),\n roles: z.record(z.string(), z.object({\n permissions: permissionsSchema,\n rate_limit: rateLimitSchema,\n })).default({}),\n}).default({}).refine((auth) => {\n if (auth.mode === 'oauth' && !auth.oauth) {\n return false;\n }\n return true;\n}, { message: 'auth.oauth config required when mode is \"oauth\"' });\n\nexport const interceptorConfigSchema = z.object({\n timeout: z.number().min(1).default(10),\n timeout_action: z.enum(['block']).default('block'),\n}).default({});\n\nconst piiActionSchema = z.enum(['block', 'redact', 'warn']);\n\nconst piiTypeActionsSchema = z.object({\n request: piiActionSchema.default('redact'),\n response: piiActionSchema.default('warn'),\n});\n\nconst customPiiTypeSchema = z.object({\n label: z.string(),\n patterns: z.array(z.object({ regex: z.string() })).min(1),\n actions: piiTypeActionsSchema,\n});\n\nexport const piiSchema = z.object({\n enabled: z.boolean().default(true),\n confidence_threshold: z.number().min(0).max(1).default(0.8),\n actions: z.record(z.string(), piiTypeActionsSchema).default({\n email: { request: 'redact', response: 'warn' },\n phone: { request: 'redact', response: 'warn' },\n ssn: { request: 'block', response: 'redact' },\n credit_card: { request: 'block', response: 'redact' },\n aws_key: { request: 'redact', response: 'redact' },\n github_token: { request: 'redact', response: 'redact' },\n }),\n custom_types: z.record(z.string(), customPiiTypeSchema).default({}),\n}).default({});\n\nexport const auditSchema = z.object({\n enabled: z.boolean().default(true),\n stdout: z.boolean().default(true),\n retention_days: z.number().min(1).default(90),\n}).default({});\n\nexport const extendsSchema = z.object({\n url: z.string().url().refine((url) => {\n const parsed = new URL(url);\n if (parsed.protocol === 'https:') return true;\n // Allow HTTP only for loopback addresses (development/testing)\n if (parsed.protocol === 'http:') {\n const host = parsed.hostname;\n return host === '127.0.0.1' || host === 'localhost' || host === '::1';\n }\n return false;\n }, 'extends URL must use HTTPS (HTTP allowed only for loopback addresses)'),\n sha256: z.string().regex(/^[a-f0-9]{64}$/i, 'SHA-256 hash must be 64 hex characters'),\n});\n\nexport const configSchema = z.object({\n extends: extendsSchema.optional(),\n servers: z.record(z.string(), serverSchema),\n daemon: daemonSchema.default({}),\n auth: authSchema,\n interceptors: interceptorConfigSchema,\n pii: piiSchema,\n audit: auditSchema,\n});\n\nexport type McpGuardConfig = z.infer<typeof configSchema>;\nexport type ServerConfig = z.infer<typeof serverSchema>;\nexport type DaemonConfig = z.infer<typeof daemonSchema>;\nexport type PolicyConfig = z.infer<typeof policySchema>;\nexport type PermissionsConfig = z.infer<typeof permissionsSchema>;\nexport type RateLimitConfig = z.infer<typeof rateLimitSchema>;\nexport type AuthConfig = z.infer<typeof authSchema>;\nexport type PIIConfig = z.infer<typeof piiSchema>;\nexport type SamplingConfig = z.infer<typeof policySchema>['sampling'];\nexport type AuditConfig = z.infer<typeof auditSchema>;\nexport type ExtendsConfig = z.infer<typeof extendsSchema>;\nexport type OAuthConfig = z.infer<typeof oauthSchema>;\nexport type ClaimsToRolesConfig = z.infer<typeof claimsToRolesSchema>;\n","export class McpGuardError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\nexport class ConfigError extends McpGuardError {\n constructor(message: string) {\n super(message, 'CONFIG_ERROR');\n }\n}\n\nexport class AuthError extends McpGuardError {\n constructor(message: string) {\n super(message, 'AUTH_ERROR');\n }\n}\n\nexport class PipelineError extends McpGuardError {\n constructor(message: string) {\n super(message, 'PIPELINE_ERROR');\n }\n}\n\nexport class StorageError extends McpGuardError {\n constructor(message: string) {\n super(message, 'STORAGE_ERROR');\n }\n}\n\nexport class BridgeError extends McpGuardError {\n constructor(message: string) {\n super(message, 'BRIDGE_ERROR');\n }\n}\n\nexport class DashboardError extends McpGuardError {\n constructor(message: string) {\n super(message, 'DASHBOARD_ERROR');\n }\n}\n\nexport class OAuthError extends McpGuardError {\n constructor(message: string) {\n super(message, 'OAUTH_ERROR');\n }\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { ConfigError } from '../errors.js';\nimport { EXTENDS_FETCH_TIMEOUT } from '../constants.js';\n\nexport interface FetchResult {\n yaml: string;\n fromCache: boolean;\n}\n\nexport function computeSha256(content: string): string {\n return createHash('sha256').update(content, 'utf-8').digest('hex');\n}\n\nexport async function fetchBaseConfig(\n url: string,\n expectedSha256: string,\n cacheDir: string,\n): Promise<FetchResult> {\n const cacheFile = join(cacheDir, `${expectedSha256}.yaml`);\n\n // Try fetching from remote\n let fetchError: Error | undefined;\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(EXTENDS_FETCH_TIMEOUT),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const yaml = await response.text();\n const actualHash = computeSha256(yaml);\n\n if (actualHash.toLowerCase() !== expectedSha256.toLowerCase()) {\n throw new ConfigError(\n `Base config SHA-256 mismatch — expected ${expectedSha256}, got ${actualHash}. ` +\n `The remote config at ${url} may have been tampered with or updated without a hash change.`,\n );\n }\n\n // Cache the verified config\n await mkdir(cacheDir, { recursive: true, mode: 0o700 });\n await writeFile(cacheFile, yaml, { mode: 0o600 });\n\n return { yaml, fromCache: false };\n } catch (err) {\n if (err instanceof ConfigError) {\n // Hash mismatch is fatal — never fall back to cache\n throw err;\n }\n fetchError = err as Error;\n }\n\n // Fetch failed — try cache\n let cachedYaml: string;\n try {\n cachedYaml = await readFile(cacheFile, 'utf-8');\n } catch {\n throw new ConfigError(\n `Failed to fetch base config from ${url} (${fetchError?.message}) and no cached copy exists. ` +\n `Cannot start without a verified base config.`,\n );\n }\n\n // Re-verify cached copy\n const cachedHash = computeSha256(cachedYaml);\n if (cachedHash.toLowerCase() !== expectedSha256.toLowerCase()) {\n throw new ConfigError(\n `Cached base config has invalid SHA-256 — expected ${expectedSha256}, got ${cachedHash}. ` +\n `Cache may be corrupted.`,\n );\n }\n\n return { yaml: cachedYaml, fromCache: true };\n}\n","import type { McpGuardConfig, PolicyConfig, PIIConfig } from './schema.js';\n\nconst PII_ACTION_SEVERITY: Record<string, number> = {\n warn: 0,\n redact: 1,\n block: 2,\n};\n\n/**\n * Merge personal config onto base config with floor semantics.\n * Personal config can only restrict, never relax base policies.\n */\nexport function mergeConfigs(\n base: McpGuardConfig,\n personal: McpGuardConfig,\n): McpGuardConfig {\n return {\n // extends is consumed during loading — not carried forward\n servers: mergeServers(base, personal),\n // Base wins for daemon, auth — personal cannot change these\n daemon: base.daemon,\n auth: base.auth,\n // Stricter interceptor timeout\n interceptors: {\n timeout: Math.min(base.interceptors.timeout, personal.interceptors.timeout),\n timeout_action: base.interceptors.timeout_action,\n },\n pii: mergePii(base.pii, personal.pii),\n audit: base.audit,\n };\n}\n\nfunction mergeServers(\n base: McpGuardConfig,\n personal: McpGuardConfig,\n): McpGuardConfig['servers'] {\n const merged: McpGuardConfig['servers'] = {};\n\n // Start with all base servers\n for (const [name, baseServer] of Object.entries(base.servers)) {\n const personalServer = personal.servers[name];\n if (!personalServer) {\n // No personal override — use base as-is\n merged[name] = baseServer;\n continue;\n }\n\n // If base policy is locked, personal overrides are ignored entirely\n if (baseServer.policy.locked) {\n merged[name] = baseServer;\n continue;\n }\n\n // Merge server config — personal can tighten but not relax\n merged[name] = {\n // Server connection config from base (personal cannot change transport/command)\n command: baseServer.command,\n args: baseServer.args,\n env: baseServer.env,\n url: baseServer.url,\n transport: baseServer.transport,\n upstream_auth_token: baseServer.upstream_auth_token,\n policy: mergePolicy(baseServer.policy, personalServer.policy),\n };\n }\n\n // Personal can add new servers (not in base)\n for (const [name, personalServer] of Object.entries(personal.servers)) {\n if (!(name in base.servers)) {\n merged[name] = personalServer;\n }\n }\n\n return merged;\n}\n\nfunction mergePolicy(base: PolicyConfig, personal: PolicyConfig): PolicyConfig {\n return {\n permissions: {\n // Intersection — only tools in BOTH lists survive\n allowed_tools: intersectLists(\n base.permissions.allowed_tools,\n personal.permissions.allowed_tools,\n ),\n // Union — all denials from both apply\n denied_tools: unionLists(base.permissions.denied_tools, personal.permissions.denied_tools),\n // Same for resources\n allowed_resources: intersectLists(\n base.permissions.allowed_resources,\n personal.permissions.allowed_resources,\n ),\n denied_resources: unionLists(base.permissions.denied_resources, personal.permissions.denied_resources),\n },\n rate_limit: {\n // Stricter (lower) value wins\n requests_per_minute: minOptional(\n base.rate_limit.requests_per_minute,\n personal.rate_limit.requests_per_minute,\n ),\n requests_per_hour: minOptional(\n base.rate_limit.requests_per_hour,\n personal.rate_limit.requests_per_hour,\n ),\n tool_limits: mergeToolLimits(base.rate_limit.tool_limits, personal.rate_limit.tool_limits),\n },\n sampling: {\n // AND — both must enable for sampling to work\n enabled: base.sampling.enabled && personal.sampling.enabled,\n max_tokens: minOptional(base.sampling.max_tokens, personal.sampling.max_tokens),\n rate_limit: minOptional(base.sampling.rate_limit, personal.sampling.rate_limit),\n // Stricter audit level wins (verbose > basic)\n audit: base.sampling.audit === 'verbose' || personal.sampling.audit === 'verbose'\n ? 'verbose' : 'basic',\n },\n locked: base.locked,\n };\n}\n\nfunction mergePii(base: PIIConfig, personal: PIIConfig): PIIConfig {\n return {\n // Base wins — personal cannot toggle PII scanning on or off\n enabled: base.enabled,\n // Lower threshold = more sensitive = stricter. Personal cannot raise it.\n confidence_threshold: Math.min(base.confidence_threshold, personal.confidence_threshold),\n // PII actions: personal can escalate (warn→block), cannot relax (block→warn)\n actions: mergePiiActions(base.actions, personal.actions),\n // Custom types: additive — personal can add, cannot remove base types\n custom_types: mergePiiCustomTypes(base.custom_types, personal.custom_types),\n };\n}\n\nfunction mergePiiActions(\n base: PIIConfig['actions'],\n personal: PIIConfig['actions'],\n): PIIConfig['actions'] {\n const merged = { ...base };\n\n for (const [type, personalAction] of Object.entries(personal)) {\n const baseAction = base[type];\n if (!baseAction) {\n // Personal adds a new PII type action — allowed\n merged[type] = personalAction;\n continue;\n }\n\n // For each direction, take the stricter (higher severity) action\n merged[type] = {\n request: stricterAction(baseAction.request, personalAction.request),\n response: stricterAction(baseAction.response, personalAction.response),\n };\n }\n\n return merged;\n}\n\nfunction mergePiiCustomTypes(\n base: PIIConfig['custom_types'],\n personal: PIIConfig['custom_types'],\n): PIIConfig['custom_types'] {\n const merged = { ...base };\n\n for (const [name, personalType] of Object.entries(personal)) {\n const baseType = base[name];\n if (!baseType) {\n // Personal adds a new type — allowed\n merged[name] = personalType;\n continue;\n }\n\n // Base type exists — personal can union patterns and escalate actions, not weaken\n merged[name] = {\n label: baseType.label,\n // Union patterns: all base patterns preserved, personal can add more\n patterns: [\n ...baseType.patterns,\n ...personalType.patterns.filter(\n (pp) => !baseType.patterns.some((bp) => bp.regex === pp.regex),\n ),\n ],\n // Actions: take the stricter of base vs personal per direction\n actions: {\n request: stricterAction(baseType.actions.request, personalType.actions.request),\n response: stricterAction(baseType.actions.response, personalType.actions.response),\n },\n };\n }\n\n return merged;\n}\n\nfunction stricterAction(\n base: 'block' | 'redact' | 'warn',\n personal: 'block' | 'redact' | 'warn',\n): 'block' | 'redact' | 'warn' {\n const baseSeverity = PII_ACTION_SEVERITY[base] ?? 0;\n const personalSeverity = PII_ACTION_SEVERITY[personal] ?? 0;\n return personalSeverity >= baseSeverity ? personal : base;\n}\n\nfunction intersectLists(\n base: string[] | undefined,\n personal: string[] | undefined,\n): string[] | undefined {\n // If base is undefined (no restriction), personal can set restrictions\n if (base === undefined) return personal;\n // If personal is undefined (no restriction), base restrictions apply\n if (personal === undefined) return base;\n // Both defined: intersection — only items in both survive\n const baseSet = new Set(base);\n return personal.filter((item) => baseSet.has(item));\n}\n\nfunction unionLists(base: string[], personal: string[]): string[] {\n return [...new Set([...base, ...personal])];\n}\n\nfunction minOptional(a: number | undefined, b: number | undefined): number | undefined {\n if (a === undefined) return b;\n if (b === undefined) return a;\n return Math.min(a, b);\n}\n\nfunction mergeToolLimits(\n base: Record<string, { requests_per_minute?: number }>,\n personal: Record<string, { requests_per_minute?: number }>,\n): Record<string, { requests_per_minute?: number }> {\n const merged = { ...base };\n for (const [tool, personalLimit] of Object.entries(personal)) {\n const baseLimit = base[tool];\n if (!baseLimit) {\n merged[tool] = personalLimit;\n continue;\n }\n merged[tool] = {\n requests_per_minute: minOptional(\n baseLimit.requests_per_minute,\n personalLimit.requests_per_minute,\n ),\n };\n }\n return merged;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport yaml from 'js-yaml';\nimport { configSchema, type McpGuardConfig } from './schema.js';\nimport { ConfigError } from '../errors.js';\nimport { fetchBaseConfig } from './fetcher.js';\nimport { mergeConfigs } from './merger.js';\nimport { DEFAULT_EXTENDS_CACHE_DIR } from '../constants.js';\n\nfunction interpolateEnvVars(content: string): string {\n return content.replace(/\\$\\{([^}]+)\\}/g, (_match, varName: string) => {\n const value = process.env[varName];\n if (value === undefined) {\n throw new ConfigError(`Unresolved environment variable: \\${${varName}}`);\n }\n return value;\n });\n}\n\nfunction parseAndValidate(content: string, source: string): McpGuardConfig {\n const interpolated = interpolateEnvVars(content);\n const raw = yaml.load(interpolated);\n\n const result = configSchema.safeParse(raw);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` ${i.path.join('.')}: ${i.message}`).join('\\n');\n throw new ConfigError(`Invalid config (${source}):\\n${issues}`);\n }\n\n return result.data;\n}\n\nexport async function loadConfig(configPath?: string): Promise<McpGuardConfig> {\n const path = configPath ?? process.env['MCP_GUARD_CONFIG'] ?? 'mcp-guard.yaml';\n\n let content: string;\n try {\n content = await readFile(path, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new ConfigError(`Config file not found: ${path}`);\n }\n throw new ConfigError(`Failed to read config file: ${path} — ${String(err)}`);\n }\n\n const personalConfig = parseAndValidate(content, path);\n\n // If config has extends, fetch base and merge\n if (personalConfig.extends) {\n const cacheDir = join(personalConfig.daemon.home, DEFAULT_EXTENDS_CACHE_DIR);\n const { yaml: baseYaml } = await fetchBaseConfig(\n personalConfig.extends.url,\n personalConfig.extends.sha256,\n cacheDir,\n );\n\n const baseConfig = parseAndValidate(baseYaml, personalConfig.extends.url);\n const merged = mergeConfigs(baseConfig, personalConfig);\n return Object.freeze(merged) as McpGuardConfig;\n }\n\n return Object.freeze(personalConfig) as McpGuardConfig;\n}\n\n// Cache the last resolved base config to avoid re-fetching on every hot reload.\n// The cache is keyed by sha256 — if the personal config changes its extends.sha256,\n// the base is re-fetched. If only policy fields change, the cached base is reused.\nlet cachedBase: { sha256: string; config: McpGuardConfig } | undefined;\n\n/**\n * Reload config from disk. Reuses the cached base config if the extends\n * sha256 hasn't changed, avoiding a network round-trip on every file save.\n */\nexport async function reloadConfig(configPath: string): Promise<McpGuardConfig> {\n const path = configPath;\n\n let content: string;\n try {\n content = await readFile(path, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new ConfigError(`Config file not found: ${path}`);\n }\n throw new ConfigError(`Failed to read config file: ${path} — ${String(err)}`);\n }\n\n const personalConfig = parseAndValidate(content, path);\n\n if (personalConfig.extends) {\n const sha256 = personalConfig.extends.sha256;\n\n // Reuse cached base if sha256 matches (avoids network fetch)\n if (cachedBase && cachedBase.sha256 === sha256) {\n const merged = mergeConfigs(cachedBase.config, personalConfig);\n return Object.freeze(merged) as McpGuardConfig;\n }\n\n // sha256 changed or no cache — full fetch\n const cacheDir = join(personalConfig.daemon.home, DEFAULT_EXTENDS_CACHE_DIR);\n const { yaml: baseYaml } = await fetchBaseConfig(\n personalConfig.extends.url,\n sha256,\n cacheDir,\n );\n\n const baseConfig = parseAndValidate(baseYaml, personalConfig.extends.url);\n cachedBase = { sha256, config: baseConfig };\n const merged = mergeConfigs(baseConfig, personalConfig);\n return Object.freeze(merged) as McpGuardConfig;\n }\n\n cachedBase = undefined;\n return Object.freeze(personalConfig) as McpGuardConfig;\n}\n","import { Command } from 'commander';\nimport { readFile, unlink } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { loadConfig } from './config/loader.js';\nimport { startDaemon } from './daemon/index.js';\nimport { startBridge } from './bridge/index.js';\nimport { isDaemonRunning } from './daemon/auto-start.js';\nimport { openDatabase, deriveDbEncryptionKey } from './storage/sqlite.js';\nimport { queryAuditLogs, formatAuditRow } from './audit/query.js';\nimport { readDaemonKey } from './identity/daemon-key.js';\nimport type { HealthResponse } from './dashboard/health.js';\nimport { executeOAuthFlow } from './identity/oauth-flow.js';\nimport { createTokenStore } from './identity/token-store.js';\nimport { registerInitCommand } from './cli/init.js';\n\nconst program = new Command()\n .name('mcp-guard')\n .description('Security proxy for MCP servers')\n .version('0.1.0');\n\nprogram\n .command('start')\n .description('Start the MCP-Guard daemon')\n .option('-c, --config <path>', 'Path to config file')\n .option('-d, --daemon', 'Run in background (detached)')\n .action(async (opts: { config?: string; daemon?: boolean }) => {\n if (opts.daemon) {\n // Fork and detach\n const { fork } = await import('node:child_process');\n const child = fork(process.argv[1], ['start', '--config', opts.config ?? 'mcp-guard.yaml'], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n console.log(`Daemon started (PID: ${child.pid})`);\n process.exit(0);\n }\n\n try {\n const config = await loadConfig(opts.config);\n await startDaemon(config, opts.config);\n } catch (err) {\n console.error(`Failed to start daemon: ${err}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('stop')\n .description('Stop the running daemon')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n try {\n const config = await loadConfig(opts.config);\n const pidFile = join(config.daemon.home, 'daemon.pid');\n const pidStr = await readFile(pidFile, 'utf-8');\n const pid = parseInt(pidStr.trim(), 10);\n\n process.kill(pid, 'SIGTERM');\n console.log(`Sent SIGTERM to daemon (PID: ${pid})`);\n\n // Wait for exit\n const maxWait = 10_000;\n const interval = 200;\n let waited = 0;\n\n while (waited < maxWait) {\n await new Promise((r) => setTimeout(r, interval));\n waited += interval;\n try {\n process.kill(pid, 0); // Check if still alive\n } catch {\n console.log('Daemon stopped');\n return;\n }\n }\n\n // Force kill\n console.log('Daemon did not stop in time — sending SIGKILL');\n process.kill(pid, 'SIGKILL');\n\n try {\n await unlink(pidFile);\n } catch {\n // Already cleaned up\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n console.log('Daemon is not running (no PID file)');\n } else if (code === 'ESRCH') {\n console.log('Daemon process not found — cleaning up stale PID file');\n } else {\n console.error(`Failed to stop daemon: ${err}`);\n process.exit(1);\n }\n }\n });\n\nprogram\n .command('connect')\n .description('Start a bridge to proxy an MCP server through the daemon')\n .requiredOption('-s, --server <name>', 'Server name from config')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { server: string; config?: string }) => {\n try {\n const config = await loadConfig(opts.config);\n await startBridge(opts.server, opts.config, {\n socketPath: config.daemon.socket_path,\n keyPath: join(config.daemon.home, 'daemon.key'),\n home: config.daemon.home,\n });\n } catch (err) {\n console.error(`Bridge failed: ${err}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('status')\n .description('Show daemon status')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n const config = await loadConfig(opts.config);\n const running = await isDaemonRunning(config.daemon.socket_path);\n if (running) {\n try {\n const pidFile = join(config.daemon.home, 'daemon.pid');\n const pidStr = await readFile(pidFile, 'utf-8');\n console.log(`Daemon is running (PID: ${pidStr.trim()})`);\n } catch {\n console.log('Daemon is running');\n }\n } else {\n console.log('Daemon is not running');\n }\n });\n\nprogram\n .command('health')\n .description('Check daemon health (exit 0 if healthy, 1 if not)')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n const config = await loadConfig(opts.config);\n try {\n // Read actual bound port from file (supports port 0 / OS-assigned)\n const portPath = join(config.daemon.home, 'dashboard.port');\n let dashboardPort = config.daemon.dashboard_port;\n try {\n const portStr = await readFile(portPath, 'utf-8');\n dashboardPort = parseInt(portStr.trim(), 10);\n } catch {\n // Port file not found — use config value\n }\n const res = await fetch(`http://127.0.0.1:${dashboardPort}/healthz`);\n const health = await res.json() as HealthResponse;\n console.log(JSON.stringify(health, null, 2));\n process.exit(health.status === 'healthy' ? 0 : 1);\n } catch {\n // Fall back to socket check\n const running = await isDaemonRunning(config.daemon.socket_path);\n if (running) {\n console.log('Daemon is running (health endpoint unavailable)');\n process.exit(0);\n }\n console.log('Daemon is not running');\n process.exit(1);\n }\n });\n\nprogram\n .command('dashboard-token')\n .description('Display the dashboard auth token')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n const config = await loadConfig(opts.config);\n const tokenPath = join(config.daemon.home, 'dashboard.token');\n try {\n const token = await readFile(tokenPath, 'utf-8');\n console.log(token.trim());\n } catch {\n console.log('No dashboard token found — start the daemon first');\n process.exit(1);\n }\n });\n\nprogram\n .command('validate')\n .description('Validate config file')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n try {\n await loadConfig(opts.config);\n console.log('Config is valid');\n } catch (err) {\n console.error(`Config validation failed: ${err}`);\n process.exit(1);\n }\n });\n\nprogram\n .command('logs')\n .description('Query audit logs')\n .option('-c, --config <path>', 'Path to config file')\n .option('-s, --server <name>', 'Filter by server name')\n .option('--last <duration>', 'Time range (e.g., 1h, 24h, 7d)')\n .option('-u, --user <name>', 'Filter by username')\n .option('-m, --method <method>', 'Filter by MCP method')\n .option('-t, --type <type>', 'Filter by type (allow/block)')\n .option('-l, --limit <count>', 'Maximum results', '100')\n .action(\n async (opts: {\n config?: string;\n server?: string;\n last?: string;\n user?: string;\n method?: string;\n type?: string;\n limit: string;\n }) => {\n let db: ReturnType<typeof openDatabase> | undefined;\n try {\n const config = await loadConfig(opts.config);\n const dbPath = join(config.daemon.home, 'mcp-guard.db');\n const dbOptions: { path: string; encryptionKey?: string } = { path: dbPath };\n if (config.daemon.encryption.enabled) {\n const keyPath = join(config.daemon.home, 'daemon.key');\n try {\n const daemonKey = await readDaemonKey(keyPath);\n dbOptions.encryptionKey = deriveDbEncryptionKey(daemonKey);\n } catch {\n console.error('Cannot read daemon key for encrypted database — is the daemon running?');\n process.exit(1);\n }\n }\n db = openDatabase(dbOptions);\n\n const parsedLimit = parseInt(opts.limit, 10);\n const limit = Number.isNaN(parsedLimit) || parsedLimit < 1 ? 100 : Math.min(parsedLimit, 10000);\n\n const rows = queryAuditLogs(db, {\n server: opts.server,\n last: opts.last,\n user: opts.user,\n method: opts.method,\n type: opts.type as 'allow' | 'block' | undefined,\n limit,\n });\n\n if (rows.length === 0) {\n console.log('No audit log entries found');\n } else {\n for (const row of rows) {\n console.log(formatAuditRow(row));\n }\n console.log(`\\n${rows.length} entries`);\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'SQLITE_CANTOPEN' || code === 'ENOENT') {\n console.log('No audit database found — is the daemon running?');\n } else {\n console.error(`Failed to query logs: ${err}`);\n process.exit(1);\n }\n } finally {\n db?.close();\n }\n },\n );\n\nconst authCmd = program\n .command('auth')\n .description('Manage OAuth authentication');\n\nauthCmd\n .command('login')\n .description('Authenticate with the configured OAuth provider')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n try {\n const config = await loadConfig(opts.config);\n if (config.auth.mode !== 'oauth' || !config.auth.oauth) {\n console.error('OAuth is not configured (auth.mode must be \"oauth\")');\n process.exit(1);\n }\n const result = await executeOAuthFlow({\n issuer: config.auth.oauth.issuer,\n clientId: config.auth.oauth.client_id,\n clientSecret: config.auth.oauth.client_secret,\n scopes: config.auth.oauth.scopes,\n });\n const store = createTokenStore(config.daemon.home);\n await store.save('default', {\n access_token: result.access_token,\n refresh_token: result.refresh_token,\n id_token: result.id_token,\n expires_at: result.expires_at,\n scope: result.scope,\n });\n console.log('Authentication successful — token stored');\n } catch (err) {\n console.error(`Authentication failed: ${err}`);\n process.exit(1);\n }\n });\n\nauthCmd\n .command('status')\n .description('Show current OAuth token status')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n try {\n const config = await loadConfig(opts.config);\n const store = createTokenStore(config.daemon.home);\n const token = await store.load('default');\n if (!token) {\n console.log('Not authenticated — run `mcp-guard auth login`');\n return;\n }\n const now = Math.floor(Date.now() / 1000);\n const expired = token.expires_at < now;\n const remaining = token.expires_at - now;\n console.log(`Status: ${expired ? 'EXPIRED' : 'Valid'}`);\n if (!expired) {\n console.log(`Expires in: ${Math.floor(remaining / 60)} minutes`);\n }\n console.log(`Scope: ${token.scope}`);\n // Decode JWT payload to show subject (without verifying — just for display)\n try {\n const parts = token.access_token.split('.');\n if (parts.length === 3) {\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());\n console.log(`Subject: ${payload.sub ?? 'unknown'}`);\n }\n } catch {\n // Opaque token — no subject to display\n }\n } catch (err) {\n console.error(`Failed to check status: ${err}`);\n process.exit(1);\n }\n });\n\nauthCmd\n .command('logout')\n .description('Remove stored OAuth tokens')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (opts: { config?: string }) => {\n try {\n const config = await loadConfig(opts.config);\n const store = createTokenStore(config.daemon.home);\n await store.remove('default');\n console.log('Logged out — tokens removed');\n } catch (err) {\n console.error(`Failed to logout: ${err}`);\n process.exit(1);\n }\n });\n\nregisterInitCommand(program);\n\nprogram.parse();\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { McpGuardConfig } from '../config/schema.js';\nimport { ensureDaemonKey } from '../identity/daemon-key.js';\nimport { openDatabase, deriveDbEncryptionKey } from '../storage/sqlite.js';\nimport { runMigrations } from '../storage/migrations.js';\nimport { createSocketServer } from './socket-server.js';\nimport { createServerManager } from './server-manager.js';\nimport { createProxyServer } from '../proxy/mcp-server.js';\nimport { registerShutdownHandlers } from './shutdown.js';\nimport { createLogger } from '../logger.js';\nimport { createPipeline } from '../interceptors/pipeline.js';\nimport { createAuthInterceptor } from '../interceptors/auth.js';\nimport { createRateLimitInterceptor } from '../interceptors/rate-limit.js';\nimport { createPermissionInterceptor } from '../interceptors/permissions.js';\nimport { createSamplingGuardInterceptor } from '../interceptors/sampling-guard.js';\nimport { createPiiInterceptor } from '../interceptors/pii-detect.js';\nimport { createPIIRegistry } from '../pii/registry.js';\nimport { createRateLimitStore } from '../storage/rate-limit-store.js';\nimport { createAuditStore } from '../audit/store.js';\nimport { createAuditTap } from '../audit/tap.js';\nimport { resolveIdentity } from '../identity/roles.js';\nimport { filterToolsList, filterResourcesList, filterCapabilities } from '../proxy/capability-filter.js';\nimport type { InterceptorContext } from '../interceptors/types.js';\nimport { createConfigWatcher } from '../config/watcher.js';\nimport { createDashboardServer } from '../dashboard/server.js';\n\nexport interface DaemonHandle {\n shutdown(): Promise<void>;\n getDashboardPort(): number;\n getDashboardToken(): string;\n}\n\nexport async function startDaemon(config: McpGuardConfig, configPath?: string): Promise<DaemonHandle> {\n const logger = createLogger({\n component: 'daemon',\n });\n\n const home = config.daemon.home;\n\n // Derive all state paths from config.daemon.home\n const keyPath = join(home, 'daemon.key');\n const pidFile = join(home, 'daemon.pid');\n const dbPath = join(home, 'mcp-guard.db');\n\n // 1. Ensure home directory\n await mkdir(home, { recursive: true, mode: 0o700 });\n logger.info('Home directory ready', { path: home });\n\n // 2. Ensure daemon key\n const daemonKey = await ensureDaemonKey(keyPath);\n logger.info('Daemon key ready');\n\n // 3. Write PID file\n await writeFile(pidFile, String(process.pid), { mode: 0o600 });\n logger.info('PID file written', { pid: process.pid, path: pidFile });\n\n // 4. Open database and run migrations\n const dbOptions: { path: string; encryptionKey?: string } = { path: dbPath };\n if (config.daemon.encryption.enabled) {\n dbOptions.encryptionKey = deriveDbEncryptionKey(daemonKey);\n logger.info('Database encryption enabled');\n }\n const db = openDatabase(dbOptions);\n runMigrations(db);\n logger.info('Database ready', { path: dbPath });\n\n // 5. Create server manager and connect to upstream servers\n const serverManager = createServerManager(config, logger);\n await serverManager.startAll();\n\n // 6. Create proxy server\n const upstreamClients = new Map<string, import('../proxy/mcp-client.js').UpstreamClient>();\n for (const name of Object.keys(config.servers)) {\n const client = serverManager.getClient(name);\n if (client) {\n upstreamClients.set(name, client);\n }\n }\n const proxyServer = createProxyServer(upstreamClients, logger);\n\n // 7. Create interceptor pipeline\n const rateLimitStore = createRateLimitStore(db);\n const auditStore = createAuditStore(db);\n const auditTap = createAuditTap(auditStore, logger, config);\n\n let currentConfig = config;\n\n function buildPipelines(cfg: McpGuardConfig) {\n const registry = createPIIRegistry(cfg.pii);\n return {\n pipeline: createPipeline({\n interceptors: [\n createAuthInterceptor(cfg),\n createRateLimitInterceptor(rateLimitStore, cfg),\n createPermissionInterceptor(cfg),\n createSamplingGuardInterceptor(cfg),\n createPiiInterceptor(registry, cfg),\n ],\n timeout: cfg.interceptors.timeout * 1000,\n logger,\n }),\n responsePipeline: createPipeline({\n interceptors: [createPiiInterceptor(registry, cfg)],\n timeout: cfg.interceptors.timeout * 1000,\n logger,\n }),\n };\n }\n\n let { pipeline: currentPipeline, responsePipeline: currentResponsePipeline } = buildPipelines(config);\n\n logger.info('Interceptor pipeline ready', {\n interceptors: ['auth', 'rate-limit', 'permissions', 'sampling-guard', 'pii-detect'],\n timeout: config.interceptors.timeout,\n });\n\n // 8. Create socket server\n const socketServer = createSocketServer({\n socketPath: config.daemon.socket_path,\n daemonKey,\n logger,\n onConnection: (conn) => {\n conn.onMessage(async (msg) => {\n if (msg.type === 'mcp') {\n // Resolve identity per-message so hot reload role changes apply immediately\n const identity = resolveIdentity(conn.uid, conn.pid, currentConfig);\n const method = msg.data.method ?? 'unknown';\n const startTime = Date.now();\n\n // Wrap entire handler in try/catch to ensure audit tap fires\n // even on unexpected runtime errors (structural audit guarantee)\n try {\n const ctx: InterceptorContext = {\n message: { method, params: msg.data.params },\n server: msg.server,\n identity,\n direction: 'request',\n metadata: { bridgeId: conn.id, timestamp: Date.now() },\n };\n\n // Run pipeline\n const pipelineResult = await currentPipeline.execute(ctx);\n const latencyMs = Date.now() - startTime;\n\n // Use pipeline-resolved identity (may be OAuth identity instead of OS identity)\n const effectiveIdentity = pipelineResult.resolvedIdentity ?? identity;\n\n // Audit tap records everything (including blocks)\n auditTap.record({\n bridgeId: conn.id,\n server: msg.server,\n method,\n direction: 'request',\n identity: effectiveIdentity,\n toolOrResource: extractToolOrResource(msg.data),\n pipelineResult,\n latencyMs,\n });\n\n if (!pipelineResult.allowed) {\n const blockReason = pipelineResult.decisions.find(\n (d) => d.decision.action === 'BLOCK',\n );\n conn.send({\n type: 'mcp',\n data: {\n jsonrpc: '2.0',\n id: msg.data.id,\n error: {\n code: -32600,\n message: blockReason?.decision.action === 'BLOCK'\n ? blockReason.decision.reason\n : 'Blocked by security policy',\n },\n },\n });\n return;\n }\n\n // Forward to upstream (with potentially modified params)\n const upstreamMsg = pipelineResult.finalParams\n ? { ...msg.data, params: pipelineResult.finalParams }\n : msg.data;\n const response = await proxyServer.handleMessage(upstreamMsg, msg.server);\n\n // Run response-direction PII scanning on result AND error payloads\n // No outer pii.enabled guard — interceptor checks internally, audit tap must always fire\n const responseContent = response.result ?? response.error;\n if (responseContent) {\n const responseCtx: InterceptorContext = {\n message: { method, params: responseContent as Record<string, unknown> },\n server: msg.server,\n identity: effectiveIdentity,\n direction: 'response',\n metadata: { bridgeId: conn.id, timestamp: Date.now() },\n };\n\n const responseResult = await currentResponsePipeline.execute(responseCtx);\n\n auditTap.record({\n bridgeId: conn.id,\n server: msg.server,\n method,\n direction: 'response',\n identity: effectiveIdentity,\n toolOrResource: extractToolOrResource(msg.data),\n pipelineResult: responseResult,\n latencyMs: Date.now() - startTime,\n });\n\n if (!responseResult.allowed) {\n conn.send({\n type: 'mcp',\n data: {\n jsonrpc: '2.0',\n id: msg.data.id,\n error: { code: -32600, message: 'Response blocked by PII policy' },\n },\n });\n return;\n }\n\n if (responseResult.finalParams) {\n if (response.result) {\n response.result = responseResult.finalParams;\n } else if (response.error) {\n // Apply redacted fields back to the typed error structure\n const redacted = responseResult.finalParams;\n if (typeof redacted['message'] === 'string') {\n response.error.message = redacted['message'];\n }\n if ('data' in redacted) {\n response.error.data = redacted['data'];\n }\n }\n }\n }\n\n // Filter sampling capability from initialize response\n if (msg.data.method === 'initialize' && response.result) {\n const result = response.result as { capabilities?: Record<string, unknown> };\n const serverConfig = currentConfig.servers[msg.server];\n if (result.capabilities && serverConfig) {\n result.capabilities = filterCapabilities(result.capabilities, serverConfig);\n }\n }\n\n // Apply capability filtering to list responses\n if (msg.data.method === 'tools/list' && response.result) {\n const result = response.result as { tools?: Array<{ name: string }> };\n const serverConfig = currentConfig.servers[msg.server];\n if (result.tools && serverConfig) {\n result.tools = filterToolsList(result.tools, serverConfig, effectiveIdentity, currentConfig);\n }\n }\n\n if (msg.data.method === 'resources/list' && response.result) {\n const result = response.result as { resources?: Array<{ uri: string }> };\n const serverConfig = currentConfig.servers[msg.server];\n if (result.resources && serverConfig) {\n result.resources = filterResourcesList(result.resources, serverConfig, effectiveIdentity, currentConfig);\n }\n }\n\n conn.send({ type: 'mcp', data: response });\n } catch (err) {\n const latencyMs = Date.now() - startTime;\n logger.error('Message handler failed', { error: String(err), method });\n\n // Audit tap MUST fire even on unexpected errors\n auditTap.record({\n bridgeId: conn.id,\n server: msg.server,\n method,\n direction: 'request',\n identity,\n toolOrResource: extractToolOrResource(msg.data),\n pipelineResult: {\n allowed: false,\n decisions: [{\n interceptor: 'internal',\n decision: { action: 'BLOCK', reason: `Internal error: ${String(err)}` },\n durationMs: latencyMs,\n }],\n },\n latencyMs,\n });\n\n conn.send({\n type: 'mcp',\n data: {\n jsonrpc: '2.0',\n id: msg.data.id,\n error: { code: -32603, message: 'Internal error' },\n },\n });\n }\n }\n });\n },\n });\n\n await socketServer.listen();\n\n // 9. Start dashboard HTTP server\n const dashboardServer = createDashboardServer({\n port: config.daemon.dashboard_port,\n healthContext: {\n startTime: Date.now(),\n getServerStatuses: () => serverManager.getStatus(),\n getBridgeCount: () => socketServer.getConnections().length,\n isDatabaseHealthy: () => {\n try { db.pragma('integrity_check'); return true; } catch { return false; }\n },\n getLastAuditWrite: () => auditTap.getLastWriteTime(),\n },\n logger,\n home,\n });\n await dashboardServer.listen();\n\n // 10. Set up config watcher for hot reload\n let configWatcher: { stop(): void } | undefined;\n if (configPath) {\n configWatcher = createConfigWatcher(\n configPath,\n (newConfig, oldConfig) => {\n // Warn about server definition changes that require restart\n for (const name of Object.keys(newConfig.servers)) {\n const oldServer = oldConfig.servers[name];\n const newServer = newConfig.servers[name];\n if (!oldServer) {\n logger.warn('New server added in config — requires daemon restart to take effect', { server: name });\n continue;\n }\n if (\n oldServer.command !== newServer.command ||\n oldServer.url !== newServer.url ||\n oldServer.transport !== newServer.transport ||\n JSON.stringify(oldServer.args) !== JSON.stringify(newServer.args) ||\n JSON.stringify(oldServer.env) !== JSON.stringify(newServer.env)\n ) {\n logger.warn('Server definition changed — requires daemon restart to take effect', { server: name });\n }\n }\n for (const name of Object.keys(oldConfig.servers)) {\n if (!newConfig.servers[name]) {\n logger.warn('Server removed in config — requires daemon restart to take effect', { server: name });\n }\n }\n\n logger.info('Config reloaded, rebuilding pipeline');\n const rebuilt = buildPipelines(newConfig);\n currentPipeline = rebuilt.pipeline;\n currentResponsePipeline = rebuilt.responsePipeline;\n currentConfig = newConfig;\n },\n logger,\n config,\n );\n logger.info('Config watcher started', { path: configPath });\n }\n\n // 11. Register shutdown handlers (single unified shutdown path)\n const shutdownHandle = registerShutdownHandlers({\n socketServer,\n serverManager,\n db,\n pidFile,\n timeout: config.daemon.shutdown_timeout * 1000,\n logger,\n onBeforeShutdown: async () => {\n configWatcher?.stop();\n await dashboardServer.close();\n },\n });\n\n logger.info('Daemon started', {\n socket: config.daemon.socket_path,\n servers: Object.keys(config.servers),\n pid: process.pid,\n dashboard: config.daemon.dashboard_port,\n });\n\n return {\n shutdown() {\n return shutdownHandle.shutdown();\n },\n getDashboardPort() {\n return dashboardServer.getPort();\n },\n getDashboardToken() {\n return dashboardServer.getAuthToken();\n },\n };\n}\n\nfunction extractToolOrResource(data: { method?: string; params?: Record<string, unknown> }): string | undefined {\n if (data.method === 'tools/call') {\n return data.params?.['name'] as string | undefined;\n }\n if (data.method === 'resources/read') {\n return data.params?.['uri'] as string | undefined;\n }\n return undefined;\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\nimport { readFile, writeFile, mkdir, stat, chmod } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { AuthError } from '../errors.js';\nimport { DEFAULT_DAEMON_KEY_PATH, DAEMON_KEY_BYTES } from '../constants.js';\n\nexport async function ensureDaemonKey(keyPath?: string): Promise<Buffer> {\n const path = keyPath ?? DEFAULT_DAEMON_KEY_PATH;\n\n try {\n const stats = await stat(path);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n throw new AuthError(\n `Daemon key has insecure permissions: ${mode.toString(8)} (expected 600): ${path}`,\n );\n }\n return await readFile(path);\n } catch (err) {\n if (err instanceof AuthError) throw err;\n const errCode = (err as NodeJS.ErrnoException).code;\n if (errCode !== 'ENOENT') {\n throw new AuthError(`Failed to read daemon key: ${err}`);\n }\n // Key doesn't exist — generate it\n }\n\n const dir = dirname(path);\n await mkdir(dir, { recursive: true, mode: 0o700 });\n\n const key = randomBytes(DAEMON_KEY_BYTES);\n await writeFile(path, key, { mode: 0o600 });\n\n return key;\n}\n\nexport async function readDaemonKey(keyPath?: string): Promise<Buffer> {\n const path = keyPath ?? DEFAULT_DAEMON_KEY_PATH;\n\n try {\n const stats = await stat(path);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n throw new AuthError(\n `Daemon key has insecure permissions: ${mode.toString(8)} (expected 600): ${path}`,\n );\n }\n return await readFile(path);\n } catch (err) {\n if (err instanceof AuthError) throw err;\n throw new AuthError(`Daemon key not found: ${path}`);\n }\n}\n\nexport function verifyDaemonKey(presented: Buffer, expected: Buffer): boolean {\n if (presented.length !== expected.length) {\n return false;\n }\n return timingSafeEqual(presented, expected);\n}\n\nexport async function ensureKeyPermissions(keyPath?: string): Promise<void> {\n const path = keyPath ?? DEFAULT_DAEMON_KEY_PATH;\n await chmod(path, 0o600);\n}\n","import Database from 'better-sqlite3-multiple-ciphers';\nimport { chmodSync } from 'node:fs';\nimport { hkdfSync } from 'node:crypto';\nimport { StorageError } from '../errors.js';\n\nexport interface DatabaseOptions {\n path: string;\n encryptionKey?: string;\n}\n\nexport function deriveDbEncryptionKey(daemonKey: Buffer): string {\n const derived = hkdfSync('sha256', daemonKey, 'mcp-guard', 'mcp-guard-db-encryption', 32);\n return Buffer.from(derived).toString('hex');\n}\n\nexport function openDatabase(options: DatabaseOptions): Database.Database {\n try {\n const db = new Database(options.path);\n\n if (options.encryptionKey) {\n if (!/^[a-f0-9]+$/i.test(options.encryptionKey)) {\n throw new StorageError('Encryption key must be hex-encoded');\n }\n db.pragma(`key=\"x'${options.encryptionKey}'\"`);\n }\n\n db.pragma('journal_mode = WAL');\n db.pragma('busy_timeout = 5000');\n db.pragma('foreign_keys = ON');\n\n if (options.path !== ':memory:') {\n chmodSync(options.path, 0o600);\n }\n\n return db;\n } catch (err) {\n throw new StorageError(`Failed to open database: ${options.path} — ${String(err)}`);\n }\n}\n\nexport function closeDatabase(db: Database.Database): void {\n try {\n checkpointWal(db);\n db.close();\n } catch (err) {\n throw new StorageError(`Failed to close database: ${String(err)}`);\n }\n}\n\nexport function checkpointWal(db: Database.Database): void {\n try {\n db.pragma('wal_checkpoint(TRUNCATE)');\n } catch (err) {\n throw new StorageError(`WAL checkpoint failed: ${String(err)}`);\n }\n}\n","import type Database from 'better-sqlite3-multiple-ciphers';\nimport { StorageError } from '../errors.js';\n\ninterface Migration {\n name: string;\n up(db: Database.Database): void;\n}\n\nconst migrations: Migration[] = [\n {\n name: '001-schema-migrations',\n up(db) {\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n name TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n },\n },\n {\n name: '002-daemon-state',\n up(db) {\n db.exec(`\n CREATE TABLE IF NOT EXISTS daemon_state (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n },\n },\n {\n name: '003-audit-logs',\n up(db) {\n db.exec(`\n CREATE TABLE audit_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL DEFAULT (datetime('now')),\n bridge_id TEXT NOT NULL,\n server TEXT NOT NULL,\n method TEXT NOT NULL,\n direction TEXT NOT NULL CHECK(direction IN ('request', 'response')),\n identity_uid INTEGER NOT NULL,\n identity_username TEXT NOT NULL,\n identity_roles TEXT NOT NULL,\n tool_or_resource TEXT,\n params_summary TEXT,\n interceptor_decisions TEXT NOT NULL,\n allowed INTEGER NOT NULL,\n blocked_by TEXT,\n block_reason TEXT,\n latency_ms REAL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n\n CREATE INDEX idx_audit_server ON audit_logs(server);\n CREATE INDEX idx_audit_timestamp ON audit_logs(timestamp);\n CREATE INDEX idx_audit_method ON audit_logs(method);\n CREATE INDEX idx_audit_identity ON audit_logs(identity_username);\n `);\n },\n },\n {\n name: '004-rate-limits',\n up(db) {\n db.exec(`\n CREATE TABLE rate_limits (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key TEXT NOT NULL UNIQUE,\n tokens REAL NOT NULL,\n max_tokens REAL NOT NULL,\n refill_rate REAL NOT NULL,\n last_refill TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n },\n },\n];\n\nexport function runMigrations(db: Database.Database): void {\n // Ensure schema_migrations table exists for the first migration\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n name TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n\n const applied = new Set(\n db\n .prepare('SELECT name FROM schema_migrations')\n .all()\n .map((row) => (row as { name: string }).name),\n );\n\n for (const migration of migrations) {\n if (applied.has(migration.name)) {\n continue;\n }\n\n const transaction = db.transaction(() => {\n migration.up(db);\n db.prepare('INSERT INTO schema_migrations (name) VALUES (?)').run(migration.name);\n });\n\n try {\n transaction();\n } catch (err) {\n throw new StorageError(`Migration '${migration.name}' failed: ${String(err)}`);\n }\n }\n}\n","import { createServer, type Server, type Socket } from 'node:net';\nimport { randomUUID } from 'node:crypto';\nimport { unlinkSync } from 'node:fs';\nimport { chmodSync } from 'node:fs';\nimport { verifyDaemonKey } from '../identity/daemon-key.js';\nimport { getPeerCredentials, verifyPeerIsCurrentUser } from '../identity/os-identity.js';\nimport type { BridgeMessage, DaemonMessage } from '../bridge/types.js';\nimport type { Logger } from '../logger.js';\nimport { AUTH_TIMEOUT, MAX_MESSAGE_SIZE } from '../constants.js';\n\nexport interface SocketServerOptions {\n socketPath: string;\n daemonKey: Buffer;\n onConnection: (conn: AuthenticatedConnection) => void;\n logger: Logger;\n}\n\nexport interface AuthenticatedConnection {\n id: string;\n uid: number;\n pid?: number;\n send(message: DaemonMessage): void;\n onMessage(handler: (message: BridgeMessage) => void): void;\n close(): void;\n}\n\nexport interface SocketServer {\n listen(): Promise<void>;\n close(): Promise<void>;\n getConnections(): AuthenticatedConnection[];\n}\n\nfunction writeFramed(socket: Socket, data: DaemonMessage): void {\n const json = JSON.stringify(data);\n const payload = Buffer.from(json, 'utf-8');\n const header = Buffer.alloc(4);\n header.writeUInt32BE(payload.length, 0);\n socket.write(Buffer.concat([header, payload]));\n}\n\nfunction createFrameParser(onMessage: (data: unknown) => void): (chunk: Buffer) => void {\n let buffer = Buffer.alloc(0);\n\n return (chunk: Buffer) => {\n buffer = Buffer.concat([buffer, chunk]);\n\n while (buffer.length >= 4) {\n const length = buffer.readUInt32BE(0);\n\n if (length > MAX_MESSAGE_SIZE) {\n buffer = Buffer.alloc(0);\n return;\n }\n\n if (buffer.length < 4 + length) {\n break; // Wait for more data\n }\n\n const json = buffer.subarray(4, 4 + length).toString('utf-8');\n buffer = buffer.subarray(4 + length);\n\n try {\n onMessage(JSON.parse(json));\n } catch {\n // Invalid JSON — skip frame\n }\n }\n };\n}\n\nexport function createSocketServer(options: SocketServerOptions): SocketServer {\n const { socketPath, daemonKey, onConnection, logger } = options;\n const connections = new Map<string, AuthenticatedConnection>();\n let server: Server;\n\n function handleSocket(socket: Socket) {\n let authenticated = false;\n let connId: string | undefined;\n const messageHandlers: ((message: BridgeMessage) => void)[] = [];\n\n // Auth timeout — close if not authenticated within AUTH_TIMEOUT\n const authTimer = setTimeout(() => {\n if (!authenticated) {\n logger.warn('Connection auth timeout — closing');\n socket.destroy();\n }\n }, AUTH_TIMEOUT);\n\n const parser = createFrameParser((data) => {\n const msg = data as BridgeMessage;\n\n if (!authenticated) {\n if (msg.type !== 'auth') {\n socket.destroy();\n return;\n }\n\n // Verify daemon key\n const presented = Buffer.from(msg.key, 'hex');\n if (!verifyDaemonKey(presented, daemonKey)) {\n writeFramed(socket, { type: 'auth_fail', reason: 'Invalid daemon key' });\n socket.destroy();\n return;\n }\n\n // Verify peer credentials\n try {\n // SAFETY: socket._handle.fd is the internal file descriptor used by koffi\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fd = (socket as any)._handle?.fd;\n if (fd !== undefined) {\n const creds = getPeerCredentials(fd);\n if (!verifyPeerIsCurrentUser(creds)) {\n writeFramed(socket, { type: 'auth_fail', reason: 'UID mismatch' });\n socket.destroy();\n return;\n }\n\n connId = randomUUID();\n authenticated = true;\n clearTimeout(authTimer);\n\n const conn: AuthenticatedConnection = {\n id: connId,\n uid: creds.uid,\n pid: creds.pid,\n send: (message) => {\n if (!socket.destroyed) writeFramed(socket, message);\n },\n onMessage: (handler) => messageHandlers.push(handler),\n close: () => socket.destroy(),\n };\n\n connections.set(connId, conn);\n writeFramed(socket, { type: 'auth_ok' });\n logger.info('Bridge authenticated', { bridge: connId, uid: creds.uid, pid: creds.pid });\n onConnection(conn);\n } else {\n writeFramed(socket, { type: 'auth_fail', reason: 'Cannot verify peer credentials' });\n socket.destroy();\n }\n } catch (err) {\n logger.error('Peer credential check failed', { error: String(err) });\n writeFramed(socket, { type: 'auth_fail', reason: 'Credential check failed' });\n socket.destroy();\n }\n return;\n }\n\n // Authenticated — forward to handlers\n for (const handler of messageHandlers) {\n handler(msg);\n }\n });\n\n socket.on('data', parser);\n\n socket.on('close', () => {\n clearTimeout(authTimer);\n if (connId) {\n connections.delete(connId);\n logger.info('Bridge disconnected', { bridge: connId });\n }\n });\n\n socket.on('error', (err) => {\n logger.error('Socket error', { bridge: connId, error: String(err) });\n });\n }\n\n return {\n async listen() {\n // Remove stale socket file\n try {\n unlinkSync(socketPath);\n } catch {\n // Doesn't exist — fine\n }\n\n server = createServer(handleSocket);\n\n return new Promise<void>((resolve, reject) => {\n server.on('error', reject);\n server.listen(socketPath, () => {\n chmodSync(socketPath, 0o600);\n logger.info('Socket server listening', { path: socketPath });\n resolve();\n });\n });\n },\n\n async close() {\n for (const conn of connections.values()) {\n conn.send({ type: 'shutdown', reason: 'daemon stopping' });\n conn.close();\n }\n connections.clear();\n\n return new Promise<void>((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => {\n try {\n unlinkSync(socketPath);\n } catch {\n // Already removed\n }\n resolve();\n });\n });\n },\n\n getConnections() {\n return Array.from(connections.values());\n },\n };\n}\n","import koffi from 'koffi';\nimport { AuthError } from '../errors.js';\n\nexport interface PeerCredentials {\n uid: number;\n gid: number;\n pid?: number;\n}\n\nlet getPeerCredentialsFn: ((socketFd: number) => PeerCredentials) | undefined;\n\nfunction initMacOS() {\n const lib = koffi.load('libc.dylib');\n\n const getpeereid = lib.func('int getpeereid(int, _Out_ uint32_t *, _Out_ uint32_t *)');\n const getsockopt = lib.func(\n 'int getsockopt(int, int, int, _Out_ uint8_t *, _Inout_ uint32_t *)',\n );\n\n return (socketFd: number): PeerCredentials => {\n const uidBuf = [0];\n const gidBuf = [0];\n\n const rc = getpeereid(socketFd, uidBuf, gidBuf);\n if (rc !== 0) {\n throw new AuthError(`getpeereid failed with rc=${rc}`);\n }\n\n // LOCAL_PEERPID: level=0 (SOL_LOCAL), optname=2\n const pidBuf = Buffer.alloc(4);\n const lenBuf = [4];\n const pidRc = getsockopt(socketFd, 0, 2, pidBuf, lenBuf);\n const pid = pidRc === 0 ? pidBuf.readUInt32LE(0) : undefined;\n\n return { uid: uidBuf[0], gid: gidBuf[0], pid };\n };\n}\n\nfunction initLinux() {\n const lib = koffi.load('libc.so.6');\n\n // struct ucred { pid_t pid; uid_t uid; gid_t gid; }\n // Registration is required for koffi to recognize the type in the function signature\n koffi.struct('ucred', {\n pid: 'int',\n uid: 'uint32_t',\n gid: 'uint32_t',\n });\n\n const getsockopt = lib.func('int getsockopt(int, int, int, _Out_ ucred *, _Inout_ uint32_t *)');\n\n // SOL_SOCKET=1, SO_PEERCRED=17\n return (socketFd: number): PeerCredentials => {\n const cred = { pid: 0, uid: 0, gid: 0 };\n const lenBuf = [12]; // sizeof(ucred)\n\n const rc = getsockopt(socketFd, 1, 17, cred, lenBuf);\n if (rc !== 0) {\n throw new AuthError(`getsockopt SO_PEERCRED failed with rc=${rc}`);\n }\n\n return { uid: cred.uid, gid: cred.gid, pid: cred.pid };\n };\n}\n\nexport function getPeerCredentials(socketFd: number): PeerCredentials {\n if (!getPeerCredentialsFn) {\n if (process.platform === 'darwin') {\n getPeerCredentialsFn = initMacOS();\n } else if (process.platform === 'linux') {\n getPeerCredentialsFn = initLinux();\n } else {\n throw new AuthError(`Unsupported platform for peer credentials: ${process.platform}`);\n }\n }\n return getPeerCredentialsFn(socketFd);\n}\n\nexport function verifyPeerIsCurrentUser(creds: PeerCredentials): boolean {\n if (!process.getuid) {\n throw new AuthError('process.getuid not available on this platform');\n }\n return creds.uid === process.getuid();\n}\n","import { Client } from '@modelcontextprotocol/sdk/client';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type { ServerConfig } from '../config/schema.js';\nimport type { Logger } from '../logger.js';\n\nexport interface UpstreamClientOptions {\n authToken?: string;\n}\n\nexport interface UpstreamClient {\n name: string;\n client: Client;\n status: 'connecting' | 'connected' | 'disconnected' | 'error';\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n}\n\nexport async function createUpstreamClient(\n name: string,\n config: ServerConfig,\n logger: Logger,\n options?: UpstreamClientOptions,\n): Promise<UpstreamClient> {\n let status: UpstreamClient['status'] = 'disconnected';\n\n const client = new Client({\n name: `mcp-guard-upstream-${name}`,\n version: '0.1.0',\n });\n\n const upstream: UpstreamClient = {\n name,\n client,\n get status() {\n return status;\n },\n\n async connect() {\n status = 'connecting';\n\n try {\n let transport;\n\n if (config.transport === 'sse' || config.transport === 'streamable-http') {\n if (!config.url) {\n throw new Error(`Server '${name}' has transport '${config.transport}' but no url specified`);\n }\n\n const url = new URL(config.url);\n const headers: Record<string, string> = {};\n if (options?.authToken) {\n headers['Authorization'] = `Bearer ${options.authToken}`;\n }\n\n logger.info('Connecting to upstream server', { server: name, transport: config.transport, url: config.url });\n\n if (config.transport === 'sse') {\n transport = new SSEClientTransport(url, {\n requestInit: { headers },\n });\n } else {\n transport = new StreamableHTTPClientTransport(url, {\n requestInit: { headers },\n });\n }\n\n transport.onclose = () => {\n status = 'disconnected';\n logger.info('Upstream server disconnected', { server: name });\n };\n\n transport.onerror = (err: Error) => {\n status = 'error';\n logger.error('Upstream server error', { server: name, error: String(err) });\n };\n } else {\n // stdio transport\n const command = config.command;\n if (!command) {\n throw new Error(`Server '${name}' has transport 'stdio' but no command specified`);\n }\n\n logger.info('Connecting to upstream server', { server: name, command });\n\n transport = new StdioClientTransport({\n command,\n args: config.args,\n env: { ...process.env, ...config.env } as Record<string, string>,\n });\n\n transport.onclose = () => {\n status = 'disconnected';\n logger.info('Upstream server disconnected', { server: name });\n };\n\n transport.onerror = (err) => {\n status = 'error';\n logger.error('Upstream server error', { server: name, error: String(err) });\n };\n }\n\n await client.connect(transport);\n status = 'connected';\n logger.info('Connected to upstream server', { server: name });\n } catch (err) {\n status = 'error';\n logger.error('Failed to connect to upstream server', {\n server: name,\n error: String(err),\n });\n throw err;\n }\n },\n\n async disconnect() {\n try {\n await client.close();\n } catch {\n // Best effort\n }\n status = 'disconnected';\n logger.info('Disconnected from upstream server', { server: name });\n },\n };\n\n return upstream;\n}\n","import type { McpGuardConfig } from '../config/schema.js';\nimport { createUpstreamClient, type UpstreamClient } from '../proxy/mcp-client.js';\nimport type { Logger } from '../logger.js';\n\nexport interface ServerManager {\n startAll(): Promise<void>;\n stopAll(): Promise<void>;\n getClient(serverName: string): UpstreamClient | undefined;\n getStatus(): Map<string, string>;\n}\n\nexport function createServerManager(config: McpGuardConfig, logger: Logger): ServerManager {\n const clients = new Map<string, UpstreamClient>();\n\n return {\n async startAll() {\n const entries = Object.entries(config.servers);\n logger.info('Starting upstream servers', { count: entries.length });\n\n const results = await Promise.allSettled(\n entries.map(async ([name, serverConfig]) => {\n const client = await createUpstreamClient(name, serverConfig, logger, {\n authToken: serverConfig.upstream_auth_token,\n });\n clients.set(name, client);\n await client.connect();\n }),\n );\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (result.status === 'rejected') {\n logger.error('Failed to start server', {\n server: entries[i][0],\n error: String(result.reason),\n });\n }\n }\n },\n\n async stopAll() {\n logger.info('Stopping all upstream servers', { count: clients.size });\n const promises = Array.from(clients.values()).map((c) => c.disconnect());\n await Promise.allSettled(promises);\n clients.clear();\n },\n\n getClient(serverName: string) {\n return clients.get(serverName);\n },\n\n getStatus() {\n const status = new Map<string, string>();\n for (const [name, client] of clients) {\n status.set(name, client.status);\n }\n return status;\n },\n };\n}\n","import type { JsonRpcMessage } from '../bridge/types.js';\nimport type { UpstreamClient } from './mcp-client.js';\nimport type { Logger } from '../logger.js';\n\nexport interface ProxyServer {\n handleMessage(message: JsonRpcMessage, serverName: string): Promise<JsonRpcMessage>;\n}\n\nexport function createProxyServer(\n upstreamClients: Map<string, UpstreamClient>,\n logger: Logger,\n): ProxyServer {\n async function handleMessage(\n message: JsonRpcMessage,\n serverName: string,\n ): Promise<JsonRpcMessage> {\n const upstream = upstreamClients.get(serverName);\n if (!upstream) {\n return {\n jsonrpc: '2.0',\n id: message.id,\n error: { code: -32600, message: `Unknown server: ${serverName}` },\n };\n }\n\n if (upstream.status !== 'connected') {\n return {\n jsonrpc: '2.0',\n id: message.id,\n error: { code: -32603, message: `Server '${serverName}' is not connected` },\n };\n }\n\n const { method, params, id } = message;\n if (!method) {\n return {\n jsonrpc: '2.0',\n id,\n error: { code: -32600, message: 'Missing method in request' },\n };\n }\n\n try {\n const result = await routeMethod(upstream, method, params);\n return { jsonrpc: '2.0', id, result };\n } catch (err) {\n logger.error('Upstream request failed', {\n server: serverName,\n method,\n error: String(err),\n });\n return {\n jsonrpc: '2.0',\n id,\n error: { code: -32603, message: `Upstream error: ${String(err)}` },\n };\n }\n }\n\n return { handleMessage };\n}\n\nasync function routeMethod(\n upstream: UpstreamClient,\n method: string,\n params?: Record<string, unknown>,\n): Promise<unknown> {\n const client = upstream.client;\n\n switch (method) {\n case 'tools/list':\n return await client.listTools(params as Parameters<typeof client.listTools>[0]);\n\n case 'tools/call':\n return await client.callTool(params as Parameters<typeof client.callTool>[0]);\n\n case 'resources/list':\n return await client.listResources(params as Parameters<typeof client.listResources>[0]);\n\n case 'resources/read':\n return await client.readResource(params as Parameters<typeof client.readResource>[0]);\n\n case 'resources/list_templates':\n return await client.listResourceTemplates(\n params as Parameters<typeof client.listResourceTemplates>[0],\n );\n\n case 'prompts/list':\n return await client.listPrompts(params as Parameters<typeof client.listPrompts>[0]);\n\n case 'prompts/get':\n return await client.getPrompt(params as Parameters<typeof client.getPrompt>[0]);\n\n default:\n // Notifications and unknown methods\n if (method.startsWith('notifications/')) {\n await client.notification({ method, params } as Parameters<typeof client.notification>[0]);\n return undefined;\n }\n\n throw new Error(`Method not found: ${method}`);\n }\n}\n","import type { SocketServer } from './socket-server.js';\nimport type { ServerManager } from './server-manager.js';\nimport type Database from 'better-sqlite3-multiple-ciphers';\nimport { unlink } from 'node:fs/promises';\nimport { checkpointWal } from '../storage/sqlite.js';\nimport type { Logger } from '../logger.js';\n\nexport interface ShutdownContext {\n socketServer: SocketServer;\n serverManager: ServerManager;\n db: Database.Database;\n pidFile: string;\n timeout: number;\n logger: Logger;\n onBeforeShutdown?: () => Promise<void>;\n}\n\nexport interface ShutdownHandle {\n /** Trigger graceful shutdown. Idempotent — safe to call multiple times. */\n shutdown(signal?: string): Promise<void>;\n}\n\nexport function registerShutdownHandlers(context: ShutdownContext): ShutdownHandle {\n let shutdownPromise: Promise<void> | undefined;\n\n async function shutdown(signal: string) {\n const { socketServer, serverManager, db, pidFile, logger, onBeforeShutdown } = context;\n logger.info('Shutdown initiated', { signal });\n\n try {\n // 0. Run pre-shutdown hooks (config watcher, dashboard server)\n // Failures must not abort the rest of shutdown (DB checkpoint, PID cleanup)\n if (onBeforeShutdown) {\n try {\n await onBeforeShutdown();\n } catch (err) {\n logger.warn('Pre-shutdown hook failed', { error: String(err) });\n }\n }\n\n // 1. Stop accepting new connections + notify bridges\n await socketServer.close();\n logger.info('Socket server closed');\n\n // 2. Disconnect upstream servers\n await serverManager.stopAll();\n logger.info('Upstream servers disconnected');\n\n // 3. Checkpoint and close database\n try {\n checkpointWal(db);\n db.close();\n logger.info('Database closed');\n } catch {\n // DB may already be closed — not an error\n }\n\n // 4. Remove PID file\n try {\n await unlink(pidFile);\n } catch {\n // Already removed\n }\n\n logger.info('Shutdown complete');\n } catch (err) {\n logger.error('Shutdown error', { error: String(err) });\n throw err;\n }\n }\n\n function triggerShutdown(signal: string): Promise<void> {\n if (!shutdownPromise) {\n shutdownPromise = shutdown(signal);\n }\n return shutdownPromise;\n }\n\n // Signal handlers add process.exit after shutdown completes\n function signalHandler(signal: string) {\n const timer = setTimeout(() => {\n context.logger.warn('Shutdown timeout exceeded — forcing exit', { signal });\n process.exit(1);\n }, context.timeout);\n\n triggerShutdown(signal)\n .then(() => {\n clearTimeout(timer);\n process.exit(0);\n })\n .catch(() => {\n clearTimeout(timer);\n process.exit(1);\n });\n }\n\n process.once('SIGTERM', () => signalHandler('SIGTERM'));\n process.once('SIGINT', () => signalHandler('SIGINT'));\n\n return {\n shutdown(signal?: string) {\n return triggerShutdown(signal ?? 'programmatic');\n },\n };\n}\n","type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\ninterface LogContext {\n component: string;\n server?: string;\n bridge?: string;\n [key: string]: unknown;\n}\n\nexport interface Logger {\n debug(message: string, extra?: Record<string, unknown>): void;\n info(message: string, extra?: Record<string, unknown>): void;\n warn(message: string, extra?: Record<string, unknown>): void;\n error(message: string, extra?: Record<string, unknown>): void;\n}\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nfunction getLogLevel(): LogLevel {\n const env = process.env['MCP_GUARD_LOG_LEVEL']?.toLowerCase();\n if (env && env in LEVEL_ORDER) {\n return env as LogLevel;\n }\n return 'info';\n}\n\nexport function createLogger(defaultContext: LogContext): Logger {\n const minLevel = getLogLevel();\n\n function log(level: LogLevel, message: string, extra?: Record<string, unknown>) {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[minLevel]) {\n return;\n }\n\n const entry = {\n level,\n timestamp: new Date().toISOString(),\n ...defaultContext,\n message,\n ...extra,\n };\n\n // Write to stderr — stdout is reserved for MCP protocol in bridge\n process.stderr.write(JSON.stringify(entry) + '\\n');\n }\n\n return {\n debug: (message, extra) => log('debug', message, extra),\n info: (message, extra) => log('info', message, extra),\n warn: (message, extra) => log('warn', message, extra),\n error: (message, extra) => log('error', message, extra),\n };\n}\n","import type {\n Interceptor,\n InterceptorContext,\n InterceptorDecision,\n PipelineResult,\n} from './types.js';\nimport type { Logger } from '../logger.js';\n\nexport interface PipelineOptions {\n interceptors: Interceptor[];\n timeout: number; // ms, per interceptor\n logger: Logger;\n}\n\nexport function createPipeline(options: PipelineOptions) {\n const { interceptors, timeout, logger } = options;\n\n async function execute(ctx: InterceptorContext): Promise<PipelineResult> {\n const decisions: PipelineResult['decisions'] = [];\n let currentParams = ctx.message.params;\n\n for (const interceptor of interceptors) {\n const start = Date.now();\n let decision: InterceptorDecision;\n\n const timer = createTimeout(timeout, interceptor.name);\n try {\n decision = await Promise.race([\n interceptor.execute(ctx),\n timer.promise,\n ]);\n } catch (err) {\n timer.clear();\n // Interceptor threw or timed out → BLOCK (fail-closed)\n const durationMs = Date.now() - start;\n const reason = String(err);\n logger.error('Interceptor failed', {\n interceptor: interceptor.name,\n error: reason,\n durationMs,\n });\n\n const blockDecision: InterceptorDecision = {\n action: 'BLOCK',\n reason: `Interceptor '${interceptor.name}' failed: ${reason}`,\n };\n\n decisions.push({\n interceptor: interceptor.name,\n decision: blockDecision,\n durationMs,\n });\n\n return {\n allowed: false,\n decisions,\n finalParams: currentParams,\n };\n }\n timer.clear();\n\n const durationMs = Date.now() - start;\n\n // Validate MODIFY decisions — reject mutations to method, tool name, or resource URI\n // Only block if the value actually CHANGED (not just present in the returned params)\n if (decision.action === 'MODIFY') {\n const mutatedProtected =\n ('method' in decision.params && decision.params['method'] !== ctx.message.method) ||\n ('name' in decision.params && decision.params['name'] !== currentParams?.['name']) ||\n ('uri' in decision.params && decision.params['uri'] !== currentParams?.['uri']);\n\n if (mutatedProtected) {\n logger.error('Interceptor attempted to modify protected fields', {\n interceptor: interceptor.name,\n });\n\n const blockDecision: InterceptorDecision = {\n action: 'BLOCK',\n reason: `Interceptor '${interceptor.name}' attempted to modify protected fields`,\n };\n\n decisions.push({\n interceptor: interceptor.name,\n decision: blockDecision,\n durationMs,\n });\n\n return {\n allowed: false,\n decisions,\n finalParams: currentParams,\n };\n }\n\n // Apply modified params for next interceptor\n currentParams = { ...currentParams, ...decision.params };\n ctx = { ...ctx, message: { ...ctx.message, params: currentParams } };\n\n // If auth interceptor resolved identity (OAuth or API key), propagate to downstream\n const authMode = decision.metadata?.['authMode'] as string | undefined;\n if (authMode && decision.metadata?.['roles']) {\n const roles = decision.metadata['roles'] as string[];\n if (authMode === 'oauth') {\n ctx = {\n ...ctx,\n identity: {\n ...ctx.identity,\n roles,\n username: (decision.metadata['oauthSubject'] as string) ?? ctx.identity.username,\n authMode: 'oauth',\n oauthSubject: decision.metadata['oauthSubject'] as string,\n },\n };\n } else if (authMode === 'api_key') {\n ctx = {\n ...ctx,\n identity: {\n ...ctx.identity,\n roles,\n authMode: 'api_key',\n },\n };\n }\n }\n }\n\n decisions.push({\n interceptor: interceptor.name,\n decision,\n durationMs,\n });\n\n // Short-circuit on BLOCK\n if (decision.action === 'BLOCK') {\n return {\n allowed: false,\n decisions,\n finalParams: currentParams,\n };\n }\n }\n\n return {\n allowed: true,\n decisions,\n finalParams: currentParams,\n resolvedIdentity: ctx.identity,\n };\n }\n\n return { execute };\n}\n\nfunction createTimeout(ms: number, name: string): { promise: Promise<never>; clear: () => void } {\n let timerId: ReturnType<typeof setTimeout>;\n const promise = new Promise<never>((_, reject) => {\n timerId = setTimeout(() => reject(new Error(`Interceptor '${name}' timed out after ${ms}ms`)), ms);\n });\n // Suppress unhandled rejection if the interceptor resolves before the timer\n promise.catch(() => {});\n return {\n promise,\n clear: () => clearTimeout(timerId),\n };\n}\n","import { timingSafeEqual, createHash } from 'node:crypto';\nimport type { McpGuardConfig } from '../config/schema.js';\nimport type { Interceptor, InterceptorContext, InterceptorDecision } from './types.js';\nimport { createTokenValidator, type TokenValidator } from '../identity/token-validator.js';\nimport { resolveOAuthIdentity } from '../identity/roles.js';\nimport { OAuthError } from '../errors.js';\n\n/**\n * Auth interceptor — validates that the caller has a resolved identity with roles.\n *\n * In OS mode (default): Identity is pre-resolved from peer credentials by the daemon.\n * The interceptor verifies it's present and has roles.\n *\n * In API key mode: Validates the key against config.auth.api_keys.\n * The key is expected in ctx.message.params._api_key (stripped before forwarding).\n *\n * NOTE: In Phase 2, API key roles are validated but not yet mapped to\n * per-role permissions/rate-limits. Full role→policy resolution is Phase 4.\n */\nexport function createAuthInterceptor(config: McpGuardConfig): Interceptor {\n // Pre-hash configured API keys at creation time for constant-time comparison\n const hashedKeys = new Map<string, { roles: string[] }>();\n for (const [key, keyConfig] of Object.entries(config.auth.api_keys)) {\n const hash = createHash('sha256').update(key).digest('hex');\n hashedKeys.set(hash, keyConfig);\n }\n\n // Lazy-initialize token validator on first OAuth request (async OIDC discovery)\n let tokenValidator: TokenValidator | undefined;\n let tokenValidatorPromise: Promise<TokenValidator> | undefined;\n if (config.auth.mode === 'oauth' && config.auth.oauth) {\n tokenValidatorPromise = createTokenValidator(config.auth.oauth);\n }\n\n return {\n name: 'auth',\n\n async execute(ctx: InterceptorContext): Promise<InterceptorDecision> {\n if (config.auth.mode === 'os') {\n return validateOsIdentity(ctx);\n }\n\n if (config.auth.mode === 'oauth') {\n if (!tokenValidatorPromise) {\n return { action: 'BLOCK', reason: 'OAuth configured but token validator not initialized', code: 'OAUTH_INTERNAL' };\n }\n if (!tokenValidator) {\n tokenValidator = await tokenValidatorPromise;\n }\n return validateOAuthToken(ctx, tokenValidator, config);\n }\n\n return validateApiKey(ctx, hashedKeys);\n },\n };\n}\n\nfunction validateOsIdentity(ctx: InterceptorContext): InterceptorDecision {\n // Identity must be present (resolved by daemon on connection)\n if (!ctx.identity) {\n return { action: 'BLOCK', reason: 'No identity resolved', code: 'AUTH_MISSING' };\n }\n\n if (!ctx.identity.username) {\n return { action: 'BLOCK', reason: 'Identity has no username', code: 'AUTH_INVALID' };\n }\n\n if (!ctx.identity.roles || ctx.identity.roles.length === 0) {\n return { action: 'BLOCK', reason: 'Identity has no roles', code: 'AUTH_NO_ROLES' };\n }\n\n return { action: 'PASS' };\n}\n\nfunction validateApiKey(\n ctx: InterceptorContext,\n hashedKeys: Map<string, { roles: string[] }>,\n): InterceptorDecision {\n const apiKey = ctx.message.params?.['_api_key'] as string | undefined;\n\n if (!apiKey) {\n return { action: 'BLOCK', reason: 'API key required but not provided', code: 'AUTH_MISSING' };\n }\n\n // Constant-time comparison: hash the presented key and compare against all\n // pre-hashed keys using timingSafeEqual to prevent timing oracles\n const presentedHash = createHash('sha256').update(apiKey).digest();\n let matchedRoles: string[] | undefined;\n for (const [storedHash, keyConfig] of hashedKeys) {\n const storedBuf = Buffer.from(storedHash, 'hex');\n if (presentedHash.length === storedBuf.length && timingSafeEqual(presentedHash, storedBuf)) {\n matchedRoles = keyConfig.roles;\n break;\n }\n }\n\n if (!matchedRoles) {\n return { action: 'BLOCK', reason: 'Invalid API key', code: 'AUTH_INVALID' };\n }\n\n // Strip the _api_key from params before forwarding\n const { _api_key: _, ...cleanParams } = ctx.message.params ?? {};\n\n return {\n action: 'MODIFY',\n params: cleanParams,\n metadata: {\n authMode: 'api_key',\n roles: matchedRoles,\n },\n };\n}\n\nasync function validateOAuthToken(\n ctx: InterceptorContext,\n tokenValidator: TokenValidator,\n config: McpGuardConfig,\n): Promise<InterceptorDecision> {\n const bearerToken = ctx.message.params?.['_bearer_token'] as string | undefined;\n\n if (!bearerToken) {\n return { action: 'BLOCK', reason: 'OAuth token required but not provided', code: 'OAUTH_TOKEN_MISSING' };\n }\n\n try {\n const result = await tokenValidator.validate(bearerToken);\n\n // Map claims to roles\n const identity = resolveOAuthIdentity(result.claims as Record<string, unknown>, config);\n\n if (!identity.roles || identity.roles.length === 0) {\n return { action: 'BLOCK', reason: 'OAuth token has no mapped roles', code: 'OAUTH_NO_ROLES' };\n }\n\n // Strip _bearer_token from params before forwarding (never send credentials upstream)\n const { _bearer_token: _, ...cleanParams } = ctx.message.params ?? {};\n\n return {\n action: 'MODIFY',\n params: cleanParams,\n metadata: {\n oauthSubject: result.subject,\n roles: identity.roles,\n authMode: 'oauth',\n },\n };\n } catch (err) {\n // Sanitize error message to prevent token fragments from leaking into audit logs\n const safeReason = err instanceof OAuthError\n ? sanitizeOAuthError(err.message)\n : 'OAuth token validation failed';\n return { action: 'BLOCK', reason: safeReason, code: 'OAUTH_INVALID_TOKEN' };\n }\n}\n\n/** Strip potential JWT fragments from error messages before they reach audit logs */\nfunction sanitizeOAuthError(message: string): string {\n // Remove JWT header/payload segments (start with eyJ = base64url of '{\"')\n // AND any long base64url sequence that could be a signature segment\n return message\n .replace(/eyJ[A-Za-z0-9_-]{20,}/g, '[redacted]')\n .replace(/[A-Za-z0-9_-]{40,}/g, '[redacted]');\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport type { OAuthConfig } from '../config/schema.js';\nimport { OAuthError } from '../errors.js';\n\nexport interface TokenValidationResult {\n valid: true;\n claims: JWTPayload;\n subject: string;\n}\n\nexport interface TokenValidator {\n validate(token: string): Promise<TokenValidationResult>;\n}\n\n/**\n * Discover the JWKS URI from the issuer's OIDC discovery endpoint.\n * Falls back to the standard /.well-known/jwks.json path if discovery fails.\n */\nasync function discoverJwksUri(issuer: string): Promise<string> {\n const discoveryUrl = `${issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n try {\n const response = await fetch(discoveryUrl);\n if (response.ok) {\n const metadata = await response.json() as { jwks_uri?: string };\n if (metadata.jwks_uri && typeof metadata.jwks_uri === 'string') {\n return metadata.jwks_uri;\n }\n }\n } catch {\n // Discovery failed — fall back to standard path\n }\n return `${issuer.replace(/\\/$/, '')}/.well-known/jwks.json`;\n}\n\nexport async function createTokenValidator(config: OAuthConfig): Promise<TokenValidator> {\n // Resolve JWKS endpoint: explicit jwks_uri, or OIDC discovery, or standard fallback\n const jwksUri = config.jwks_uri ?? await discoverJwksUri(config.issuer);\n const jwks = createRemoteJWKSet(new URL(jwksUri));\n\n return {\n async validate(token: string): Promise<TokenValidationResult> {\n try {\n // Default audience to client_id — always validate who the token was issued for\n const audience = config.audience ?? config.client_id;\n const { payload } = await jwtVerify(token, jwks, {\n issuer: config.issuer,\n audience,\n clockTolerance: config.clock_tolerance_seconds,\n });\n\n if (!payload.sub) {\n throw new OAuthError('JWT missing required \"sub\" claim');\n }\n\n return {\n valid: true,\n claims: payload,\n subject: payload.sub,\n };\n } catch (err) {\n if (err instanceof OAuthError) {\n throw err;\n }\n throw new OAuthError(`JWT validation failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n },\n };\n}\n","import { userInfo } from 'node:os';\nimport type { McpGuardConfig } from '../config/schema.js';\nimport type { ResolvedIdentity } from '../interceptors/types.js';\n\n/**\n * Resolve OAuth JWT claims into a username and role list.\n *\n * Maps the configured claim (default: 'roles') through config.auth.oauth.claims_to_roles.mapping\n * to produce project-level role names. If no claims map, returns empty roles (fail-closed —\n * the auth interceptor will BLOCK with OAUTH_NO_ROLES).\n */\nexport function resolveOAuthIdentity(\n claims: Record<string, unknown>,\n config: McpGuardConfig,\n): ResolvedIdentity {\n const sub = typeof claims['sub'] === 'string' ? claims['sub'] : 'oauth-user';\n const oauthConfig = config.auth.oauth;\n\n if (!oauthConfig) {\n // No OAuth config = no role mapping possible = fail-closed (empty roles → BLOCK)\n return { uid: -1, username: sub, roles: [], authMode: 'oauth', oauthSubject: sub };\n }\n\n const claimName = oauthConfig.claims_to_roles.claim_name;\n const claimValue = claims[claimName];\n const mapping = oauthConfig.claims_to_roles.mapping;\n\n // Claim value can be a string or array of strings\n const claimValues: string[] = Array.isArray(claimValue)\n ? claimValue.filter((v): v is string => typeof v === 'string')\n : typeof claimValue === 'string'\n ? [claimValue]\n : [];\n\n // Map claim values through the mapping to get roles\n const roles: string[] = [];\n for (const value of claimValues) {\n const mapped = mapping[value];\n if (mapped) {\n roles.push(...mapped);\n }\n }\n\n // Deduplicate\n const uniqueRoles = [...new Set(roles)];\n\n // Fail-closed: in OAuth mode, if no claims map to configured roles, return empty roles.\n // The auth interceptor will BLOCK on empty roles (OAUTH_NO_ROLES).\n // This prevents valid JWTs with unmapped claims from getting default access.\n return {\n uid: -1,\n username: sub,\n roles: uniqueRoles,\n authMode: 'oauth',\n oauthSubject: sub,\n };\n}\n\n/**\n * Resolve OS identity (uid/pid) into a username and role list.\n *\n * Role resolution: config.auth.roles is keyed by role name, each containing\n * permissions and rate_limit. A username is assigned a role if the role key\n * matches their username (Phase 2 convention). If no match, ['default'].\n *\n * Phase 4 will add explicit user→role mappings via OAuth claims.\n */\nexport function resolveIdentity(\n uid: number,\n pid: number | undefined,\n config: McpGuardConfig,\n): ResolvedIdentity {\n const username = resolveUsername(uid);\n const roles = resolveRoles(username, config);\n\n return { uid, pid, username, roles };\n}\n\nfunction resolveUsername(uid: number): string {\n try {\n const info = userInfo();\n if (info.uid === uid) {\n return info.username;\n }\n } catch {\n // userInfo() can fail on some platforms\n }\n return `uid:${uid}`;\n}\n\nfunction resolveRoles(username: string, config: McpGuardConfig): string[] {\n // Collect all role names where the username matches the role key\n // Phase 2 convention: role keys that match the username are assigned\n const matchedRoles: string[] = [];\n for (const roleName of Object.keys(config.auth.roles)) {\n if (roleName === username) {\n matchedRoles.push(roleName);\n }\n }\n\n return matchedRoles.length > 0 ? matchedRoles : ['default'];\n}\n","import type { McpGuardConfig, PermissionsConfig, RateLimitConfig } from '../config/schema.js';\nimport type { ResolvedIdentity } from './types.js';\n\nexport interface EffectivePermissions {\n /**\n * Multiple allow-lists that must ALL be satisfied (semantic intersection).\n * A tool/resource must match every list to be allowed.\n * Empty array = no allow-list restrictions.\n */\n allowed_tools_lists: string[][];\n denied_tools: string[];\n allowed_resources_lists: string[][];\n denied_resources: string[];\n}\n\nexport interface EffectiveRateLimit {\n requests_per_minute?: number;\n requests_per_hour?: number;\n tool_limits: Record<string, { requests_per_minute?: number }>;\n}\n\n/**\n * Resolve effective permissions by merging server-level policy with role-level restrictions.\n * Floor-based: role permissions can only restrict, never relax the server policy.\n * - allowed_tools: each non-undefined allow-list is accumulated; a tool must match ALL lists\n * - denied_tools: union (role adds more denials)\n */\nexport function resolveEffectivePermissions(\n serverPermissions: PermissionsConfig,\n identity: ResolvedIdentity,\n config: McpGuardConfig,\n): EffectivePermissions {\n // Accumulate all allow-lists — a tool/resource must match ALL of them\n const allowedToolsLists: string[][] = [];\n const allowedResourcesLists: string[][] = [];\n\n if (serverPermissions.allowed_tools) {\n allowedToolsLists.push(serverPermissions.allowed_tools);\n }\n if (serverPermissions.allowed_resources) {\n allowedResourcesLists.push(serverPermissions.allowed_resources);\n }\n\n let deniedTools = [...serverPermissions.denied_tools];\n let deniedResources = [...serverPermissions.denied_resources];\n\n for (const role of identity.roles) {\n const roleConfig = config.auth.roles[role];\n if (!roleConfig) continue;\n\n const rolePerms = roleConfig.permissions;\n\n // Union denied (role adds more denials)\n deniedTools = [...new Set([...deniedTools, ...rolePerms.denied_tools])];\n deniedResources = [...new Set([...deniedResources, ...rolePerms.denied_resources])];\n\n // Accumulate allow-lists (each must be independently satisfied)\n if (rolePerms.allowed_tools) {\n allowedToolsLists.push(rolePerms.allowed_tools);\n }\n if (rolePerms.allowed_resources) {\n allowedResourcesLists.push(rolePerms.allowed_resources);\n }\n }\n\n return {\n allowed_tools_lists: allowedToolsLists,\n denied_tools: deniedTools,\n allowed_resources_lists: allowedResourcesLists,\n denied_resources: deniedResources,\n };\n}\n\n/**\n * Resolve effective rate limit by merging server-level with role-level.\n * Floor-based: takes the stricter (lower) value, including per-tool limits.\n */\nexport function resolveEffectiveRateLimit(\n serverRateLimit: RateLimitConfig,\n identity: ResolvedIdentity,\n config: McpGuardConfig,\n): EffectiveRateLimit {\n const effective: EffectiveRateLimit = {\n requests_per_minute: serverRateLimit.requests_per_minute,\n requests_per_hour: serverRateLimit.requests_per_hour,\n tool_limits: { ...serverRateLimit.tool_limits },\n };\n\n for (const role of identity.roles) {\n const roleConfig = config.auth.roles[role];\n if (!roleConfig) continue;\n\n const roleLimit = roleConfig.rate_limit;\n\n // Stricter (lower) value wins for top-level limits\n if (roleLimit.requests_per_minute) {\n effective.requests_per_minute = effective.requests_per_minute\n ? Math.min(effective.requests_per_minute, roleLimit.requests_per_minute)\n : roleLimit.requests_per_minute;\n }\n\n if (roleLimit.requests_per_hour) {\n effective.requests_per_hour = effective.requests_per_hour\n ? Math.min(effective.requests_per_hour, roleLimit.requests_per_hour)\n : roleLimit.requests_per_hour;\n }\n\n // Merge per-tool limits (stricter wins)\n for (const [toolName, toolLimit] of Object.entries(roleLimit.tool_limits)) {\n const existing = effective.tool_limits[toolName];\n if (!existing) {\n effective.tool_limits[toolName] = { ...toolLimit };\n } else if (toolLimit.requests_per_minute) {\n existing.requests_per_minute = existing.requests_per_minute\n ? Math.min(existing.requests_per_minute, toolLimit.requests_per_minute)\n : toolLimit.requests_per_minute;\n }\n }\n }\n\n return effective;\n}\n","import type { McpGuardConfig } from '../config/schema.js';\nimport type { RateLimitStore } from '../storage/rate-limit-store.js';\nimport type { Interceptor, InterceptorContext, InterceptorDecision } from './types.js';\nimport { resolveEffectiveRateLimit } from './effective-policy.js';\n\nexport function createRateLimitInterceptor(\n store: RateLimitStore,\n config: McpGuardConfig,\n): Interceptor {\n return {\n name: 'rate-limit',\n\n async execute(ctx: InterceptorContext): Promise<InterceptorDecision> {\n const serverConfig = config.servers[ctx.server];\n if (!serverConfig) {\n return { action: 'PASS' };\n }\n\n // Merge server-level + role-level rate limits (floor-based: stricter wins)\n const rateConfig = resolveEffectiveRateLimit(\n serverConfig.policy.rate_limit,\n ctx.identity,\n config,\n );\n\n // Check server-level rate limit\n if (rateConfig.requests_per_minute) {\n const key = `server:${ctx.server}:${ctx.identity.username}:rpm`;\n const allowed = store.tryConsume(key, {\n maxTokens: rateConfig.requests_per_minute,\n refillRate: rateConfig.requests_per_minute / 60, // tokens per second\n });\n\n if (!allowed) {\n return {\n action: 'BLOCK',\n reason: 'Rate limit exceeded (requests per minute)',\n code: 'RATE_LIMITED',\n };\n }\n }\n\n if (rateConfig.requests_per_hour) {\n const key = `server:${ctx.server}:${ctx.identity.username}:rph`;\n const allowed = store.tryConsume(key, {\n maxTokens: rateConfig.requests_per_hour,\n refillRate: rateConfig.requests_per_hour / 3600, // tokens per second\n });\n\n if (!allowed) {\n return {\n action: 'BLOCK',\n reason: 'Rate limit exceeded (requests per hour)',\n code: 'RATE_LIMITED',\n };\n }\n }\n\n // Check per-tool rate limit (only for tools/call)\n if (ctx.message.method === 'tools/call') {\n const toolName = ctx.message.params?.['name'] as string | undefined;\n if (toolName && rateConfig.tool_limits[toolName]) {\n const toolLimit = rateConfig.tool_limits[toolName];\n if (toolLimit.requests_per_minute) {\n const key = `tool:${ctx.server}:${ctx.identity.username}:${toolName}:rpm`;\n const allowed = store.tryConsume(key, {\n maxTokens: toolLimit.requests_per_minute,\n refillRate: toolLimit.requests_per_minute / 60,\n });\n\n if (!allowed) {\n return {\n action: 'BLOCK',\n reason: `Rate limit exceeded for tool '${toolName}'`,\n code: 'RATE_LIMITED',\n };\n }\n }\n }\n }\n\n return { action: 'PASS' };\n },\n };\n}\n","import type { McpGuardConfig } from '../config/schema.js';\nimport type { Interceptor, InterceptorContext, InterceptorDecision } from './types.js';\nimport { resolveEffectivePermissions } from './effective-policy.js';\n\n// Max input length for regex/glob matching to prevent ReDoS\nconst MAX_MATCH_INPUT_LENGTH = 1024;\n\n// Module-level cache for compiled regex patterns (auto-populates on first use)\nconst patternCache = new Map<string, RegExp>();\n\nexport function createPermissionInterceptor(config: McpGuardConfig): Interceptor {\n // Pre-compile all patterns at creation time into the module cache\n for (const serverConfig of Object.values(config.servers)) {\n const allPatterns = [\n ...serverConfig.policy.permissions.denied_tools,\n ...(serverConfig.policy.permissions.allowed_tools ?? []),\n ...serverConfig.policy.permissions.denied_resources,\n ...(serverConfig.policy.permissions.allowed_resources ?? []),\n ];\n for (const pattern of allPatterns) {\n if (!patternCache.has(pattern)) {\n const compiled = compilePattern(pattern);\n if (compiled) patternCache.set(pattern, compiled);\n }\n }\n }\n\n return {\n name: 'permissions',\n\n async execute(ctx: InterceptorContext): Promise<InterceptorDecision> {\n const serverConfig = config.servers[ctx.server];\n if (!serverConfig) {\n return { action: 'PASS' };\n }\n\n // Merge server-level + role-level permissions (floor-based)\n const permissions = resolveEffectivePermissions(\n serverConfig.policy.permissions,\n ctx.identity,\n config,\n );\n\n if (ctx.message.method === 'tools/call') {\n const toolName = ctx.message.params?.['name'] as string | undefined;\n if (!toolName) {\n return { action: 'BLOCK', reason: 'tools/call missing required tool name', code: 'MALFORMED_REQUEST' };\n }\n\n if (matchesAny(toolName, permissions.denied_tools)) {\n return {\n action: 'BLOCK',\n reason: `Tool '${toolName}' is denied`,\n code: 'PERMISSION_DENIED',\n };\n }\n\n // Tool must match ALL allow-lists (semantic intersection)\n for (const allowList of permissions.allowed_tools_lists) {\n if (!matchesAny(toolName, allowList)) {\n return {\n action: 'BLOCK',\n reason: `Tool '${toolName}' is not in allowed list`,\n code: 'PERMISSION_DENIED',\n };\n }\n }\n\n return { action: 'PASS' };\n }\n\n if (ctx.message.method === 'resources/read') {\n const uri = ctx.message.params?.['uri'] as string | undefined;\n if (!uri) {\n return { action: 'BLOCK', reason: 'resources/read missing required URI', code: 'MALFORMED_REQUEST' };\n }\n\n if (matchesAny(uri, permissions.denied_resources)) {\n return {\n action: 'BLOCK',\n reason: `Resource '${uri}' is denied`,\n code: 'PERMISSION_DENIED',\n };\n }\n\n // Resource must match ALL allow-lists (semantic intersection)\n for (const allowList of permissions.allowed_resources_lists) {\n if (!matchesAny(uri, allowList)) {\n return {\n action: 'BLOCK',\n reason: `Resource '${uri}' is not in allowed list`,\n code: 'PERMISSION_DENIED',\n };\n }\n }\n\n return { action: 'PASS' };\n }\n\n // Non-tool/resource methods (tools/list, resources/list, prompts/*, etc.) → PASS\n // Capability filtering happens post-pipeline\n return { action: 'PASS' };\n },\n };\n}\n\n/**\n * Check if a value matches any pattern in the list.\n * Supports: exact match, glob wildcards (*), regex (prefixed with ^).\n */\nexport function matchesAny(value: string, patterns: string[]): boolean {\n return patterns.some((pattern) => matchesPattern(value, pattern));\n}\n\nfunction matchesPattern(value: string, pattern: string): boolean {\n if (pattern.startsWith('^') || pattern.includes('*')) {\n if (value.length > MAX_MATCH_INPUT_LENGTH) {\n return false;\n }\n // Use cached compiled pattern, or compile on-demand for uncached patterns\n const compiled = patternCache.get(pattern) ?? compileAndCache(pattern);\n return compiled ? compiled.test(value) : false;\n }\n\n return value === pattern;\n}\n\nfunction compilePattern(pattern: string): RegExp | null {\n try {\n if (pattern.startsWith('^')) {\n return new RegExp(pattern);\n }\n if (pattern.includes('*')) {\n const regexStr = '^' + pattern.replace(/[.+?{}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*') + '$';\n return new RegExp(regexStr);\n }\n } catch {\n // Invalid regex — skip\n }\n return null;\n}\n\nfunction compileAndCache(pattern: string): RegExp | null {\n const compiled = compilePattern(pattern);\n if (compiled) patternCache.set(pattern, compiled);\n return compiled;\n}\n","import type { McpGuardConfig } from '../config/schema.js';\nimport type { Interceptor, InterceptorContext, InterceptorDecision } from './types.js';\n\nexport function createSamplingGuardInterceptor(config: McpGuardConfig): Interceptor {\n return {\n name: 'sampling-guard',\n\n async execute(ctx: InterceptorContext): Promise<InterceptorDecision> {\n // Only gate sampling/createMessage — all other methods pass through\n if (ctx.message.method !== 'sampling/createMessage') {\n return { action: 'PASS' };\n }\n\n const serverConfig = config.servers[ctx.server];\n if (!serverConfig) {\n // Unknown server → BLOCK (fail-closed)\n return {\n action: 'BLOCK',\n reason: `Sampling is disabled for unknown server \"${ctx.server}\"`,\n code: 'SAMPLING_DISABLED',\n };\n }\n\n if (!serverConfig.policy.sampling.enabled) {\n return {\n action: 'BLOCK',\n reason: `Sampling is disabled for server \"${ctx.server}\"`,\n code: 'SAMPLING_DISABLED',\n };\n }\n\n return { action: 'PASS' };\n },\n };\n}\n","import type { PIIMatch, PIIMatchSafe, ScanResult } from './types.js';\n\n/**\n * Replace PII matches in a string with redaction markers.\n * Returns a NEW string — the original is not mutated.\n * Processes spans in reverse order to preserve offsets.\n * Overlapping matches: sort by start, skip matches that overlap with a previous one.\n */\nexport function redactString(content: string, matches: PIIMatch[]): string {\n if (matches.length === 0) return content;\n\n // Sort by start, deduplicate overlapping spans (keep earlier match)\n const sorted = [...matches].sort((a, b) => a.start - b.start);\n const nonOverlapping: PIIMatch[] = [];\n let lastEnd = -1;\n for (const m of sorted) {\n if (m.start >= lastEnd) {\n nonOverlapping.push(m);\n lastEnd = m.end;\n }\n }\n\n // Process in reverse to preserve offsets\n let result = content;\n for (let i = nonOverlapping.length - 1; i >= 0; i--) {\n const m = nonOverlapping[i];\n const marker = `[REDACTED:${m.type}]`;\n result = result.slice(0, m.start) + marker + result.slice(m.end);\n }\n\n return result;\n}\n\n/**\n * Recursively walk a JSON-compatible value, scanning every string with the\n * provided detector function, collecting matches, and optionally redacting.\n *\n * Returns { matches, redacted } where:\n * - matches: all PIIMatch found, with `path` indicating where in the structure\n * - redacted: deep clone with matched spans replaced (original untouched)\n */\nexport function scanAndRedact(\n value: unknown,\n detect: (content: string) => PIIMatch[],\n shouldRedact: boolean,\n): ScanResult {\n const allMatches: Array<PIIMatchSafe & { path: string }> = [];\n\n function walk(val: unknown, path: string): unknown {\n if (typeof val === 'string') {\n const matches = detect(val);\n for (const m of matches) {\n // Strip value field — only type, confidence, start, end, path survive\n allMatches.push({ type: m.type, confidence: m.confidence, start: m.start, end: m.end, path });\n }\n if (shouldRedact && matches.length > 0) {\n return redactString(val, matches);\n }\n return val;\n }\n\n if (Array.isArray(val)) {\n return val.map((item, i) => walk(item, path ? `${path}[${i}]` : `[${i}]`));\n }\n\n if (val !== null && typeof val === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(val)) {\n result[key] = walk(child, path ? `${path}.${key}` : key);\n }\n return result;\n }\n\n // Numbers, booleans, null — return as-is\n return val;\n }\n\n const redacted = walk(value, '');\n\n return { matches: allMatches, redacted };\n}\n","import type { McpGuardConfig } from '../config/schema.js';\nimport type { Interceptor, InterceptorContext, InterceptorDecision } from './types.js';\nimport type { PIIRegistry } from '../pii/registry.js';\nimport type { PIIAction } from '../pii/types.js';\nimport { scanAndRedact } from '../pii/redactor.js';\n\n/** Block if serialized content exceeds 1MB — fail-closed, never pass uninspected content */\nconst MAX_SCAN_BYTES = 1_048_576;\n\n/** Action severity order for picking the strictest */\nconst ACTION_SEVERITY: Record<PIIAction, number> = {\n warn: 0,\n redact: 1,\n block: 2,\n};\n\nexport function createPiiInterceptor(\n registry: PIIRegistry,\n config: McpGuardConfig,\n): Interceptor {\n // Pre-merge action map: top-level actions + custom_types actions (custom overrides built-in if same key)\n const actionMap: Record<string, { request: PIIAction; response: PIIAction }> = { ...config.pii.actions };\n for (const [typeName, customType] of Object.entries(config.pii.custom_types)) {\n actionMap[typeName] = customType.actions;\n }\n\n return {\n name: 'pii-detect',\n\n async execute(ctx: InterceptorContext): Promise<InterceptorDecision> {\n if (!config.pii.enabled) {\n return { action: 'PASS' };\n }\n\n const params = ctx.message.params;\n if (!params) {\n return { action: 'PASS' };\n }\n\n // Size guard — block uninspected content (fail-closed)\n const serialized = JSON.stringify(params);\n if (serialized.length > MAX_SCAN_BYTES) {\n return {\n action: 'BLOCK',\n reason: 'Content exceeds 1MB PII scan limit — blocked uninspected',\n code: 'PII_CONTENT_TOO_LARGE',\n };\n }\n\n const direction = ctx.direction;\n\n const detectFn = (content: string) => registry.scan(content, { direction, server: ctx.server });\n\n // Phase 1: Scan without redaction to discover matches (no unnecessary deep clone)\n let scanResult;\n try {\n scanResult = scanAndRedact(params, detectFn, false);\n } catch (err) {\n // Detector errors → BLOCK (fail-closed)\n return {\n action: 'BLOCK',\n reason: `PII detector error: ${String(err)}`,\n code: 'PII_DETECTOR_ERROR',\n };\n }\n\n if (scanResult.matches.length === 0) {\n return { action: 'PASS' };\n }\n\n // Resolve the strictest action across all matched PII types\n let strictestAction: PIIAction = 'warn';\n const detections: Array<{ type: string; action: PIIAction }> = [];\n\n for (const match of scanResult.matches) {\n const typeActions = actionMap[match.type];\n const action: PIIAction = typeActions\n ? typeActions[direction]\n : (direction === 'request' ? 'redact' : 'warn');\n\n detections.push({ type: match.type, action });\n\n if (ACTION_SEVERITY[action] > ACTION_SEVERITY[strictestAction]) {\n strictestAction = action;\n }\n }\n\n // Metadata for audit — NEVER includes original PII values\n const metadata = {\n piiDetections: detections,\n };\n\n if (strictestAction === 'block') {\n const detectedTypes = [...new Set(detections.map((d) => d.type))].join(', ');\n return {\n action: 'BLOCK',\n reason: `PII detected (${detectedTypes}) — blocked by ${direction} policy`,\n code: 'PII_BLOCKED',\n metadata,\n };\n }\n\n if (strictestAction === 'redact') {\n // Phase 2: Only compute redacted output when action is redact\n let redactResult;\n try {\n redactResult = scanAndRedact(params, detectFn, true);\n } catch (err) {\n return {\n action: 'BLOCK',\n reason: `PII redaction error: ${String(err)}`,\n code: 'PII_DETECTOR_ERROR',\n };\n }\n\n // Strip protected fields — pipeline rejects MODIFY containing name/method/uri.\n // This is safe: pipeline merges via { ...currentParams, ...decision.params },\n // so original name/method/uri from currentParams are preserved in the merge.\n const redactedParams = { ...(redactResult.redacted as Record<string, unknown>) };\n delete redactedParams['name'];\n delete redactedParams['method'];\n delete redactedParams['uri'];\n\n return {\n action: 'MODIFY',\n params: redactedParams,\n metadata,\n };\n }\n\n // warn — pass through with metadata\n return { action: 'PASS', metadata };\n },\n };\n}\n","import type { PIIDetector, PIIMatch, DetectionContext } from './types.js';\n\n/** Max content length to scan — prevents catastrophic backtracking */\nexport const MAX_CONTENT_LENGTH = 65536;\n\ninterface PatternDef {\n type: string;\n regex: RegExp;\n confidence: number;\n validate?: (match: string) => boolean;\n}\n\n/**\n * Standard Luhn algorithm for credit card checksum validation.\n * Returns true if the digit string passes the Luhn check.\n */\nexport function luhnCheck(digits: string): boolean {\n const cleaned = digits.replace(/\\D/g, '');\n if (cleaned.length === 0) return false;\n\n let sum = 0;\n let alternate = false;\n\n for (let i = cleaned.length - 1; i >= 0; i--) {\n let n = parseInt(cleaned[i], 10);\n if (alternate) {\n n *= 2;\n if (n > 9) n -= 9;\n }\n sum += n;\n alternate = !alternate;\n }\n\n return sum % 10 === 0;\n}\n\nconst PATTERNS: PatternDef[] = [\n {\n type: 'email',\n regex: /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/g,\n confidence: 0.9,\n },\n {\n type: 'phone',\n regex: /(?:\\+?1[-.\\s]?)?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}\\b/g,\n confidence: 0.8,\n validate: (match: string) => {\n // Must have at least 10 digits to be a phone number\n const digits = match.replace(/\\D/g, '');\n return digits.length >= 10 && digits.length <= 15;\n },\n },\n {\n type: 'ssn',\n regex: /\\b(?!000|666|9\\d{2})\\d{3}-(?!00)\\d{2}-(?!0000)\\d{4}\\b/g,\n confidence: 0.95,\n },\n {\n type: 'credit_card',\n // Matches common card prefixes: Visa (4), Mastercard (5[1-5], 2[2-7]),\n // Amex (3[47]), Discover (6011, 65, 644-649)\n regex: /\\b(?:4\\d{3}|5[1-5]\\d{2}|2[2-7]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}|4[4-9]\\d))[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{1,7}\\b/g,\n confidence: 0.95,\n validate: (match: string) => {\n const digits = match.replace(/\\D/g, '');\n return digits.length >= 13 && digits.length <= 19 && luhnCheck(digits);\n },\n },\n {\n type: 'aws_key',\n regex: /\\bAKIA[0-9A-Z]{16}\\b/g,\n confidence: 0.95,\n },\n {\n type: 'github_token',\n regex: /\\b(?:ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36}\\b/g,\n confidence: 0.95,\n },\n];\n\n/**\n * Create the built-in regex-based PII detector.\n * Patterns are compiled once at module load, not per-call.\n */\nexport function createRegexDetector(): PIIDetector {\n return {\n name: 'regex',\n\n detect(content: string, _ctx: DetectionContext): PIIMatch[] {\n if (!content || content.length === 0) return [];\n\n // Cap input length to prevent catastrophic backtracking\n const scanContent = content.length > MAX_CONTENT_LENGTH\n ? content.slice(0, MAX_CONTENT_LENGTH)\n : content;\n\n const matches: PIIMatch[] = [];\n\n for (const pattern of PATTERNS) {\n // Reset lastIndex for global regexes\n pattern.regex.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = pattern.regex.exec(scanContent)) !== null) {\n const value = match[0];\n\n // Run optional validation (e.g., Luhn for credit cards)\n if (pattern.validate && !pattern.validate(value)) {\n continue;\n }\n\n matches.push({\n type: pattern.type,\n value,\n confidence: pattern.confidence,\n start: match.index,\n end: match.index + value.length,\n });\n }\n }\n\n // Sort by start position\n matches.sort((a, b) => a.start - b.start);\n return matches;\n },\n };\n}\n","import type { PIIDetector, PIIMatch, DetectionContext } from './types.js';\nimport type { PIIConfig } from '../config/schema.js';\nimport { createRegexDetector, MAX_CONTENT_LENGTH } from './regex-detector.js';\nimport { createLogger } from '../logger.js';\n\nexport interface PIIRegistry {\n /** Run all detectors against the content, return aggregated matches above confidence threshold */\n scan(content: string, ctx: DetectionContext): PIIMatch[];\n}\n\nconst logger = createLogger({ component: 'pii-registry' });\n\n/**\n * Create a PII registry with the built-in regex detector plus any custom types from config.\n * Custom regex patterns are compiled at creation time, not per-scan.\n */\nexport function createPIIRegistry(config: PIIConfig): PIIRegistry {\n const detectors: PIIDetector[] = [createRegexDetector()];\n\n // Register custom detectors from config\n for (const [typeName, customType] of Object.entries(config.custom_types)) {\n const compiledPatterns: RegExp[] = [];\n\n for (const pattern of customType.patterns) {\n try {\n compiledPatterns.push(new RegExp(pattern.regex, 'g'));\n } catch {\n logger.warn('Invalid custom PII regex, skipping', {\n type: typeName,\n regex: pattern.regex,\n });\n }\n }\n\n if (compiledPatterns.length > 0) {\n detectors.push({\n name: `custom:${typeName}`,\n detect(content: string, _ctx: DetectionContext): PIIMatch[] {\n const matches: PIIMatch[] = [];\n for (const regex of compiledPatterns) {\n regex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n matches.push({\n type: typeName,\n value: match[0],\n confidence: 0.85,\n start: match.index,\n end: match.index + match[0].length,\n });\n }\n }\n return matches;\n },\n });\n }\n }\n\n const confidenceThreshold = config.confidence_threshold;\n\n return {\n scan(content: string, ctx: DetectionContext): PIIMatch[] {\n if (!content || content.length === 0) return [];\n\n // Cap input length once for all detectors (prevents ReDoS in custom patterns)\n const scanContent = content.length > MAX_CONTENT_LENGTH\n ? content.slice(0, MAX_CONTENT_LENGTH)\n : content;\n\n const allMatches: PIIMatch[] = [];\n\n for (const detector of detectors) {\n const matches = detector.detect(scanContent, ctx);\n allMatches.push(...matches);\n }\n\n // Filter by confidence threshold\n const filtered = allMatches.filter((m) => m.confidence >= confidenceThreshold);\n\n // Sort by start position\n filtered.sort((a, b) => a.start - b.start);\n\n // Deduplicate overlapping spans — keep highest confidence\n const deduped: PIIMatch[] = [];\n for (const m of filtered) {\n const overlapping = deduped.findIndex(\n (existing) => m.start < existing.end && m.end > existing.start,\n );\n if (overlapping === -1) {\n deduped.push(m);\n } else if (m.confidence >= deduped[overlapping].confidence) {\n deduped[overlapping] = m;\n }\n }\n\n return deduped;\n },\n };\n}\n","import type Database from 'better-sqlite3-multiple-ciphers';\n\nexport interface RateLimitConfig {\n maxTokens: number;\n refillRate: number; // tokens per second\n}\n\nexport interface RateLimitStore {\n /** Try to consume one token. Returns true if allowed, false if rate limited. */\n tryConsume(key: string, config: RateLimitConfig): boolean;\n /** Get remaining tokens for a key */\n getRemaining(key: string): number | null;\n /** Clean up expired entries */\n cleanup(olderThan: Date): void;\n}\n\nexport function createRateLimitStore(db: Database.Database): RateLimitStore {\n const upsertStmt = db.prepare(`\n INSERT INTO rate_limits (key, tokens, max_tokens, refill_rate, last_refill, updated_at)\n VALUES (?, ?, ?, ?, datetime('now'), datetime('now'))\n ON CONFLICT(key) DO UPDATE SET\n tokens = excluded.tokens,\n max_tokens = excluded.max_tokens,\n refill_rate = excluded.refill_rate,\n last_refill = excluded.last_refill,\n updated_at = excluded.updated_at\n `);\n\n // Update tokens and updated_at only — preserves last_refill for denied requests\n const updateTokensStmt = db.prepare(`\n UPDATE rate_limits SET tokens = ?, updated_at = datetime('now') WHERE key = ?\n `);\n\n const selectStmt = db.prepare(`\n SELECT tokens, max_tokens, refill_rate, last_refill\n FROM rate_limits WHERE key = ?\n `);\n\n const deleteStmt = db.prepare(`\n DELETE FROM rate_limits WHERE updated_at < ?\n `);\n\n const tryConsumeTransaction = db.transaction(\n (key: string, config: RateLimitConfig): boolean => {\n const row = selectStmt.get(key) as\n | { tokens: number; max_tokens: number; refill_rate: number; last_refill: string }\n | undefined;\n\n if (!row) {\n // First request — initialize with maxTokens - 1 (consuming one)\n upsertStmt.run(key, config.maxTokens - 1, config.maxTokens, config.refillRate);\n return true;\n }\n\n // Calculate token refill — clamp to CURRENT config ceiling,\n // not the persisted max_tokens (handles tightened limits)\n const lastRefill = new Date(row.last_refill + 'Z').getTime();\n const now = Date.now();\n const elapsedSeconds = (now - lastRefill) / 1000;\n const effectiveMax = Math.min(row.max_tokens, config.maxTokens);\n const refilled = Math.min(\n effectiveMax,\n row.tokens + elapsedSeconds * config.refillRate,\n );\n\n if (refilled < 1) {\n // Rate limited — update token count but preserve last_refill\n // so the refill clock continues accumulating correctly\n updateTokensStmt.run(refilled, key);\n return false;\n }\n\n // Consume one token\n upsertStmt.run(key, refilled - 1, config.maxTokens, config.refillRate);\n return true;\n },\n );\n\n return {\n tryConsume(key: string, config: RateLimitConfig): boolean {\n return tryConsumeTransaction(key, config);\n },\n\n getRemaining(key: string): number | null {\n const row = selectStmt.get(key) as\n | { tokens: number; refill_rate: number; max_tokens: number; last_refill: string }\n | undefined;\n if (!row) return null;\n\n const lastRefill = new Date(row.last_refill + 'Z').getTime();\n const now = Date.now();\n const elapsedSeconds = (now - lastRefill) / 1000;\n return Math.min(row.max_tokens, row.tokens + elapsedSeconds * row.refill_rate);\n },\n\n cleanup(olderThan: Date): void {\n deleteStmt.run(olderThan.toISOString());\n },\n };\n}\n","import type Database from 'better-sqlite3-multiple-ciphers';\nimport type { ResolvedIdentity, PipelineResult } from '../interceptors/types.js';\n\nexport interface AuditEntry {\n bridgeId: string;\n server: string;\n method: string;\n direction: 'request' | 'response';\n identity: ResolvedIdentity;\n toolOrResource?: string;\n paramsSummary?: string;\n /** SECURITY: Only `decisions` from pipelineResult is serialized to the DB.\n * `finalParams` is intentionally NOT persisted — it may contain redacted content\n * that, if stored, would create a PII data retention concern. */\n pipelineResult: PipelineResult;\n latencyMs?: number;\n}\n\nexport interface AuditFilters {\n server?: string;\n last?: string;\n user?: string;\n method?: string;\n type?: 'allow' | 'block';\n limit?: number;\n}\n\nexport interface AuditStore {\n write(entry: AuditEntry): void;\n query(filters: AuditFilters): AuditLogRow[];\n cleanup(olderThanDays: number): number;\n}\n\nexport interface AuditLogRow {\n id: number;\n timestamp: string;\n bridge_id: string;\n server: string;\n method: string;\n direction: string;\n identity_uid: number;\n identity_username: string;\n identity_roles: string;\n tool_or_resource: string | null;\n params_summary: string | null;\n interceptor_decisions: string;\n allowed: number;\n blocked_by: string | null;\n block_reason: string | null;\n latency_ms: number | null;\n}\n\nexport function createAuditStore(db: Database.Database): AuditStore {\n const insertStmt = db.prepare(`\n INSERT INTO audit_logs (\n bridge_id, server, method, direction,\n identity_uid, identity_username, identity_roles,\n tool_or_resource, params_summary,\n interceptor_decisions, allowed, blocked_by, block_reason, latency_ms\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const cleanupStmt = db.prepare(`\n DELETE FROM audit_logs WHERE timestamp < datetime('now', ?)\n `);\n\n return {\n write(entry: AuditEntry): void {\n const blockedDecision = entry.pipelineResult.decisions.find(\n (d) => d.decision.action === 'BLOCK',\n );\n\n insertStmt.run(\n entry.bridgeId,\n entry.server,\n entry.method,\n entry.direction,\n entry.identity.uid,\n entry.identity.username,\n JSON.stringify(entry.identity.roles),\n entry.toolOrResource ?? null,\n entry.paramsSummary ?? null,\n JSON.stringify(\n entry.pipelineResult.decisions.map((d) => ({\n name: d.interceptor,\n action: d.decision.action,\n reason: d.decision.action === 'BLOCK' ? d.decision.reason : undefined,\n metadata: d.decision.metadata,\n durationMs: d.durationMs,\n })),\n ),\n entry.pipelineResult.allowed ? 1 : 0,\n blockedDecision?.interceptor ?? null,\n blockedDecision?.decision.action === 'BLOCK' ? blockedDecision.decision.reason : null,\n entry.latencyMs ?? null,\n );\n },\n\n query(filters: AuditFilters): AuditLogRow[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (filters.server) {\n conditions.push('server = ?');\n params.push(filters.server);\n }\n\n if (filters.user) {\n conditions.push('identity_username = ?');\n params.push(filters.user);\n }\n\n if (filters.method) {\n conditions.push('method = ?');\n params.push(filters.method);\n }\n\n if (filters.type === 'allow') {\n conditions.push('allowed = 1');\n } else if (filters.type === 'block') {\n conditions.push('allowed = 0');\n }\n\n if (filters.last) {\n const modifier = parseTimeModifier(filters.last);\n if (modifier) {\n conditions.push(\"timestamp >= datetime('now', ?)\");\n params.push(modifier);\n }\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = filters.limit ?? 100;\n\n const sql = `SELECT * FROM audit_logs ${where} ORDER BY timestamp DESC LIMIT ?`;\n params.push(limit);\n\n return db.prepare(sql).all(...params) as AuditLogRow[];\n },\n\n cleanup(olderThanDays: number): number {\n const days = Math.max(1, Math.abs(olderThanDays));\n const result = cleanupStmt.run(`-${days} days`);\n return result.changes;\n },\n };\n}\n\nfunction parseTimeModifier(duration: string): string | null {\n const match = duration.match(/^(\\d+)(m|h|d)$/);\n if (!match) return null;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 'm': return `-${value} minutes`;\n case 'h': return `-${value} hours`;\n case 'd': return `-${value} days`;\n default: return null;\n }\n}\n","import type { AuditEntry } from './store.js';\n\n/**\n * Format an audit entry as single-line JSON for structured stdout logging.\n * Designed for container log pipelines (ELK, Datadog, etc.).\n */\nexport function formatAuditEntry(entry: AuditEntry): string {\n const blockedDecision = entry.pipelineResult.decisions.find(\n (d) => d.decision.action === 'BLOCK',\n );\n\n return JSON.stringify({\n type: 'audit',\n timestamp: new Date().toISOString(),\n server: entry.server,\n method: entry.method,\n direction: entry.direction,\n identity: entry.identity.username,\n roles: entry.identity.roles,\n allowed: entry.pipelineResult.allowed,\n blocked_by: blockedDecision?.interceptor ?? null,\n block_reason: blockedDecision?.decision.action === 'BLOCK'\n ? blockedDecision.decision.reason\n : null,\n tool_or_resource: entry.toolOrResource ?? null,\n latency_ms: entry.latencyMs ?? null,\n });\n}\n","import type { AuditEntry, AuditStore } from './store.js';\nimport type { Logger } from '../logger.js';\nimport type { McpGuardConfig } from '../config/schema.js';\nimport { formatAuditEntry } from './stdout-logger.js';\n\nexport interface AuditTap {\n record(entry: AuditEntry): void;\n getLastWriteTime(): string | null;\n}\n\n/**\n * Structural audit tap — observes every message from outside the interceptor pipeline.\n * Cannot be skipped by pipeline errors, timeouts, or misconfig.\n *\n * Audit failures must never block requests — log the error and continue.\n */\nexport function createAuditTap(\n store: AuditStore,\n logger: Logger,\n config: McpGuardConfig,\n): AuditTap {\n let lastWriteTime: string | null = null;\n\n return {\n record(entry: AuditEntry): void {\n if (!config.audit.enabled) {\n return;\n }\n\n // Write to SQLite\n try {\n store.write(entry);\n lastWriteTime = new Date().toISOString();\n } catch (err) {\n logger.error('Audit store write failed', { error: String(err) });\n }\n\n // Write structured JSON to stdout if enabled\n if (config.audit.stdout) {\n try {\n process.stdout.write(formatAuditEntry(entry) + '\\n');\n } catch (err) {\n logger.error('Audit stdout write failed', { error: String(err) });\n }\n }\n },\n\n getLastWriteTime() {\n return lastWriteTime;\n },\n };\n}\n","import type { McpGuardConfig, ServerConfig } from '../config/schema.js';\nimport type { ResolvedIdentity } from '../interceptors/types.js';\nimport { matchesAny } from '../interceptors/permissions.js';\nimport { resolveEffectivePermissions } from '../interceptors/effective-policy.js';\n\n/**\n * Filter the initialize response to remove sampling capability if disabled.\n * Returns a modified capabilities object (new object, not mutated).\n */\nexport function filterCapabilities(\n capabilities: Record<string, unknown>,\n serverConfig: ServerConfig,\n): Record<string, unknown> {\n if (!serverConfig.policy.sampling.enabled && 'sampling' in capabilities) {\n const { sampling: _, ...rest } = capabilities;\n return rest;\n }\n return capabilities;\n}\n\n/**\n * Filter tools/list response to remove denied tools.\n * Uses the same matching logic as the permission interceptor.\n */\nexport function filterToolsList(\n tools: Array<{ name: string; [key: string]: unknown }>,\n serverConfig: ServerConfig,\n identity: ResolvedIdentity,\n config: McpGuardConfig,\n): Array<{ name: string; [key: string]: unknown }> {\n // Merge server-level + role-level permissions for capability filtering\n const permissions = resolveEffectivePermissions(serverConfig.policy.permissions, identity, config);\n\n return tools.filter((tool) => {\n if (matchesAny(tool.name, permissions.denied_tools)) {\n return false;\n }\n\n // Tool must match ALL allow-lists\n for (const allowList of permissions.allowed_tools_lists) {\n if (!matchesAny(tool.name, allowList)) {\n return false;\n }\n }\n\n return true;\n });\n}\n\n/**\n * Filter resources/list response to remove denied resources.\n */\nexport function filterResourcesList(\n resources: Array<{ uri: string; [key: string]: unknown }>,\n serverConfig: ServerConfig,\n identity: ResolvedIdentity,\n config: McpGuardConfig,\n): Array<{ uri: string; [key: string]: unknown }> {\n const permissions = resolveEffectivePermissions(serverConfig.policy.permissions, identity, config);\n\n return resources.filter((resource) => {\n if (matchesAny(resource.uri, permissions.denied_resources)) {\n return false;\n }\n\n for (const allowList of permissions.allowed_resources_lists) {\n if (!matchesAny(resource.uri, allowList)) {\n return false;\n }\n }\n\n return true;\n });\n}\n","import { watch, type FSWatcher } from 'node:fs';\nimport type { Logger } from '../logger.js';\nimport type { McpGuardConfig } from './schema.js';\nimport { reloadConfig } from './loader.js';\nimport { CONFIG_RELOAD_DEBOUNCE } from '../constants.js';\n\nexport interface ConfigWatcher {\n stop(): void;\n}\n\nexport function createConfigWatcher(\n configPath: string,\n onChange: (newConfig: McpGuardConfig, oldConfig: McpGuardConfig) => void,\n logger: Logger,\n currentConfig: McpGuardConfig,\n): ConfigWatcher {\n let oldConfig = currentConfig;\n let debounceTimer: ReturnType<typeof setTimeout> | undefined;\n let watcher: FSWatcher;\n\n try {\n watcher = watch(configPath, { persistent: false }, (_eventType) => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(async () => {\n try {\n const newConfig = await reloadConfig(configPath);\n const previousConfig = oldConfig;\n oldConfig = newConfig;\n onChange(newConfig, previousConfig);\n logger.info('Config reloaded successfully');\n } catch (err) {\n logger.warn('Config reload failed — keeping previous config', {\n error: String(err),\n });\n }\n }, CONFIG_RELOAD_DEBOUNCE);\n });\n } catch (err) {\n logger.error('Failed to watch config file — hot reload disabled', { error: String(err), path: configPath });\n return { stop() {} };\n }\n\n return {\n stop() {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n watcher.close();\n },\n };\n}\n","import { createServer, type Server } from 'node:http';\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\nimport { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Logger } from '../logger.js';\nimport type { HealthContext } from './health.js';\nimport { buildHealthResponse } from './health.js';\nimport { DashboardError } from '../errors.js';\n\nexport interface DashboardServer {\n listen(): Promise<void>;\n close(): Promise<void>;\n getAuthToken(): string;\n getPort(): number;\n}\n\nexport interface DashboardServerOptions {\n port: number;\n healthContext: HealthContext;\n authToken?: string;\n logger: Logger;\n home?: string;\n}\n\nexport function createDashboardServer(options: DashboardServerOptions): DashboardServer {\n const { port, healthContext, logger } = options;\n const authToken = options.authToken ?? randomBytes(32).toString('hex');\n const authTokenBuffer = Buffer.from(authToken, 'utf-8');\n\n const server: Server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n\n if (url.pathname === '/healthz' && req.method === 'GET') {\n const health = buildHealthResponse(healthContext);\n const statusCode = health.status === 'unhealthy' ? 503 : 200;\n res.writeHead(statusCode, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(health));\n return;\n }\n\n if (url.pathname === '/api/status' && req.method === 'GET') {\n if (!verifyBearerToken(req.headers.authorization, authTokenBuffer)) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n\n const health = buildHealthResponse(healthContext);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(health));\n return;\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n });\n\n return {\n async listen() {\n await new Promise<void>((resolve, reject) => {\n server.on('error', (err) => {\n reject(new DashboardError(`Dashboard server failed to start: ${err.message}`));\n });\n server.listen(port, '127.0.0.1', () => {\n logger.info('Dashboard server started', { port });\n resolve();\n });\n });\n\n // Persist token and actual port for CLI access\n if (options.home) {\n const actualPort = String(server.address() && typeof server.address() === 'object'\n ? (server.address() as { port: number }).port\n : port);\n const tokenPath = join(options.home, 'dashboard.token');\n const portPath = join(options.home, 'dashboard.port');\n await writeFile(tokenPath, authToken, { mode: 0o600 });\n await writeFile(portPath, actualPort, { mode: 0o600 });\n }\n },\n\n async close() {\n await new Promise<void>((resolve, reject) => {\n server.close((err) => {\n if (err) {\n reject(new DashboardError(`Dashboard server close failed: ${err.message}`));\n } else {\n logger.info('Dashboard server closed');\n resolve();\n }\n });\n });\n },\n\n getAuthToken() {\n return authToken;\n },\n\n getPort() {\n const addr = server.address();\n if (addr && typeof addr === 'object') {\n return addr.port;\n }\n return port;\n },\n };\n}\n\nfunction verifyBearerToken(\n authHeader: string | undefined,\n expectedTokenBuffer: Buffer,\n): boolean {\n if (!authHeader?.startsWith('Bearer ')) {\n return false;\n }\n\n const provided = Buffer.from(authHeader.slice(7), 'utf-8');\n if (provided.length !== expectedTokenBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(provided, expectedTokenBuffer);\n}\n","import { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction loadVersion(): string {\n // Walk up from the current file (or bundled dist/) to find package.json\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 5; i++) {\n try {\n const content = readFileSync(join(dir, 'package.json'), 'utf-8');\n const pkg = JSON.parse(content) as { version?: string };\n if (pkg.version) return pkg.version;\n } catch {\n // Not found at this level, go up\n }\n dir = dirname(dir);\n }\n return '0.0.0';\n}\n\nconst VERSION = loadVersion();\n\nexport interface HealthContext {\n startTime: number;\n getServerStatuses: () => Map<string, string>;\n getBridgeCount: () => number;\n isDatabaseHealthy: () => boolean;\n getLastAuditWrite: () => string | null;\n}\n\nexport interface HealthResponse {\n status: 'healthy' | 'degraded' | 'unhealthy';\n uptime_seconds: number;\n servers: Record<string, string>;\n bridges: number;\n database: 'ok' | 'error';\n last_audit_write: string | null;\n version: string;\n}\n\nexport function buildHealthResponse(ctx: HealthContext): HealthResponse {\n const serverStatuses = ctx.getServerStatuses();\n const dbHealthy = ctx.isDatabaseHealthy();\n const servers: Record<string, string> = {};\n\n for (const [name, status] of serverStatuses) {\n servers[name] = status;\n }\n\n const serverValues = [...serverStatuses.values()];\n const allConnected = serverValues.length > 0 && serverValues.every((s) => s === 'connected');\n const noneConnected = serverValues.length === 0 || serverValues.every((s) => s !== 'connected');\n\n let status: HealthResponse['status'];\n if (!dbHealthy || noneConnected) {\n status = 'unhealthy';\n } else if (allConnected) {\n status = 'healthy';\n } else {\n status = 'degraded';\n }\n\n return {\n status,\n uptime_seconds: Math.floor((Date.now() - ctx.startTime) / 1000),\n servers,\n bridges: ctx.getBridgeCount(),\n database: dbHealthy ? 'ok' : 'error',\n last_audit_write: ctx.getLastAuditWrite(),\n version: VERSION,\n };\n}\n","import { connect } from 'node:net';\nimport { authenticateToDaemon } from './auth.js';\nimport { isDaemonRunning, autoStartDaemon } from '../daemon/auto-start.js';\nimport { DEFAULT_SOCKET_PATH, DEFAULT_DAEMON_KEY_PATH, DEFAULT_HOME, MAX_MESSAGE_SIZE } from '../constants.js';\nimport { BridgeError } from '../errors.js';\nimport { createTokenStore } from '../identity/token-store.js';\n\nexport interface BridgeOptions {\n socketPath?: string;\n keyPath?: string;\n home?: string;\n}\n\nexport async function startBridge(\n serverName: string,\n configPath?: string,\n options?: BridgeOptions,\n): Promise<void> {\n const socketPath = options?.socketPath ?? DEFAULT_SOCKET_PATH;\n const keyPath = options?.keyPath ?? DEFAULT_DAEMON_KEY_PATH;\n const home = options?.home ?? DEFAULT_HOME;\n\n // 0. Load stored OAuth token only when config uses OAuth mode\n // Never inject tokens in non-OAuth modes to prevent credential leakage to upstream servers\n let bearerToken: string | undefined;\n try {\n const { loadConfig } = await import('../config/loader.js');\n const bridgeConfig = await loadConfig(configPath);\n if (bridgeConfig.auth.mode === 'oauth') {\n const tokenStore = createTokenStore(home);\n const stored = await tokenStore.load(serverName) ?? await tokenStore.load('default');\n if (stored) {\n const now = Math.floor(Date.now() / 1000);\n if (stored.expires_at > now) {\n bearerToken = stored.access_token;\n } else {\n process.stderr.write('OAuth token expired — run `mcp-guard auth login` to refresh\\n');\n }\n }\n }\n } catch {\n // Config or token read failed — proceed without (daemon will BLOCK if oauth mode)\n }\n\n // 1. Ensure daemon is running\n if (!(await isDaemonRunning(socketPath))) {\n await autoStartDaemon(configPath, socketPath);\n }\n\n // 2. Connect to daemon\n const socket = connect(socketPath);\n\n await new Promise<void>((resolve, reject) => {\n socket.on('connect', resolve);\n socket.on('error', (err) => reject(new BridgeError(`Cannot connect to daemon: ${err.message}`)));\n });\n\n // 3. Authenticate\n await authenticateToDaemon(socket, keyPath);\n\n // 4. Pipe stdin → daemon\n let stdinBuffer = Buffer.alloc(0);\n process.stdin.on('data', (chunk: Buffer) => {\n stdinBuffer = Buffer.concat([stdinBuffer, chunk]);\n\n // Try to parse complete JSON-RPC messages (newline-delimited from MCP clients)\n while (true) {\n const newline = stdinBuffer.indexOf(0x0a); // \\n\n if (newline === -1) break;\n\n const line = stdinBuffer.subarray(0, newline).toString('utf-8').trim();\n stdinBuffer = stdinBuffer.subarray(newline + 1);\n\n if (line.length === 0) continue;\n\n try {\n const data = JSON.parse(line);\n // Inject bearer token into MCP message params if available\n if (bearerToken && data.params) {\n data.params = { ...data.params, _bearer_token: bearerToken };\n } else if (bearerToken && !data.params) {\n data.params = { _bearer_token: bearerToken };\n }\n // Send as framed bridge message\n const msg = JSON.stringify({ type: 'mcp', server: serverName, data });\n const payload = Buffer.from(msg, 'utf-8');\n const header = Buffer.alloc(4);\n header.writeUInt32BE(payload.length, 0);\n socket.write(Buffer.concat([header, payload]));\n } catch {\n // Not valid JSON — skip\n }\n }\n });\n\n // 5. Pipe daemon → stdout\n let socketBuffer = Buffer.alloc(0);\n socket.on('data', (chunk: Buffer) => {\n socketBuffer = Buffer.concat([socketBuffer, chunk]);\n\n while (socketBuffer.length >= 4) {\n const length = socketBuffer.readUInt32BE(0);\n if (length > MAX_MESSAGE_SIZE) {\n socketBuffer = Buffer.alloc(0);\n return;\n }\n if (socketBuffer.length < 4 + length) break;\n\n const json = socketBuffer.subarray(4, 4 + length).toString('utf-8');\n socketBuffer = socketBuffer.subarray(4 + length);\n\n try {\n const msg = JSON.parse(json) as { type: string; data?: unknown; reason?: string };\n\n if (msg.type === 'mcp' && msg.data) {\n process.stdout.write(JSON.stringify(msg.data) + '\\n');\n } else if (msg.type === 'shutdown') {\n process.exit(1);\n } else if (msg.type === 'error') {\n process.stderr.write(`Daemon error: ${JSON.stringify(msg)}\\n`);\n }\n } catch {\n // Invalid JSON — skip\n }\n }\n });\n\n // 6. Handle stream close\n process.stdin.on('end', () => {\n socket.destroy();\n process.exit(0);\n });\n\n socket.on('close', () => {\n process.exit(1);\n });\n\n socket.on('error', (err) => {\n process.stderr.write(`Bridge socket error: ${err.message}\\n`);\n process.exit(1);\n });\n}\n","import type { Socket } from 'node:net';\nimport { readDaemonKey } from '../identity/daemon-key.js';\nimport { AuthError } from '../errors.js';\nimport { AUTH_TIMEOUT } from '../constants.js';\n\nfunction writeFramed(socket: Socket, data: unknown): void {\n const json = JSON.stringify(data);\n const payload = Buffer.from(json, 'utf-8');\n const header = Buffer.alloc(4);\n header.writeUInt32BE(payload.length, 0);\n socket.write(Buffer.concat([header, payload]));\n}\n\nfunction readFramed(socket: Socket, timeout: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let buffer = Buffer.alloc(0);\n const timer = setTimeout(() => {\n cleanup();\n reject(new AuthError('Auth response timeout'));\n }, timeout);\n\n function onData(chunk: Buffer) {\n buffer = Buffer.concat([buffer, chunk]);\n\n if (buffer.length >= 4) {\n const length = buffer.readUInt32BE(0);\n if (buffer.length >= 4 + length) {\n cleanup();\n const json = buffer.subarray(4, 4 + length).toString('utf-8');\n try {\n resolve(JSON.parse(json));\n } catch {\n reject(new AuthError('Invalid auth response'));\n }\n }\n }\n }\n\n function onError(err: Error) {\n cleanup();\n reject(new AuthError(`Socket error during auth: ${err.message}`));\n }\n\n function cleanup() {\n clearTimeout(timer);\n socket.removeListener('data', onData);\n socket.removeListener('error', onError);\n }\n\n socket.on('data', onData);\n socket.on('error', onError);\n });\n}\n\nexport async function authenticateToDaemon(\n socket: Socket,\n keyPath?: string,\n): Promise<void> {\n const key = await readDaemonKey(keyPath);\n writeFramed(socket, { type: 'auth', key: key.toString('hex') });\n\n const response = (await readFramed(socket, AUTH_TIMEOUT)) as { type: string; reason?: string };\n\n if (response.type !== 'auth_ok') {\n const reason = response.reason ?? 'Unknown auth failure';\n throw new AuthError(`Daemon auth failed: ${reason}`);\n }\n}\n","import { connect } from 'node:net';\nimport { fork } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { DEFAULT_SOCKET_PATH } from '../constants.js';\nimport { BridgeError } from '../errors.js';\n\nexport async function isDaemonRunning(socketPath?: string): Promise<boolean> {\n const path = socketPath ?? DEFAULT_SOCKET_PATH;\n\n return new Promise((resolve) => {\n const socket = connect(path);\n const timeout = setTimeout(() => {\n socket.destroy();\n resolve(false);\n }, 1000);\n\n socket.on('connect', () => {\n clearTimeout(timeout);\n socket.destroy();\n resolve(true);\n });\n\n socket.on('error', () => {\n clearTimeout(timeout);\n resolve(false);\n });\n });\n}\n\nexport async function autoStartDaemon(configPath?: string, socketPath?: string): Promise<void> {\n // Fork the CLI process with 'start' command in background mode\n const thisFile = fileURLToPath(import.meta.url);\n const cliPath = join(dirname(thisFile), '..', 'cli.js');\n\n const args = ['start', '--daemon'];\n if (configPath) {\n args.push('--config', configPath);\n }\n\n const child = fork(cliPath, args, {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Wait for socket to become available\n const maxWait = 3000;\n const interval = 100;\n let waited = 0;\n\n while (waited < maxWait) {\n await new Promise((r) => setTimeout(r, interval));\n waited += interval;\n\n if (await isDaemonRunning(socketPath)) {\n return;\n }\n }\n\n throw new BridgeError('Daemon failed to start within timeout');\n}\n","import { readFile, writeFile, unlink, readdir, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { OAUTH_TOKEN_DIR, OAUTH_TOKEN_FILE_MODE } from '../constants.js';\nimport { OAuthError } from '../errors.js';\n\nexport interface StoredToken {\n access_token: string;\n refresh_token?: string;\n id_token?: string;\n expires_at: number; // Unix epoch seconds\n scope: string;\n server?: string;\n}\n\nexport interface TokenStore {\n save(name: string, token: StoredToken): Promise<void>;\n load(name: string): Promise<StoredToken | null>;\n remove(name: string): Promise<void>;\n list(): Promise<string[]>;\n}\n\nexport function createTokenStore(home: string): TokenStore {\n const tokenDir = join(home, OAUTH_TOKEN_DIR);\n\n async function ensureDir(): Promise<void> {\n await mkdir(tokenDir, { recursive: true, mode: 0o700 });\n }\n\n function tokenPath(name: string): string {\n // Sanitize name to prevent path traversal\n const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(tokenDir, `${safeName}.json`);\n }\n\n return {\n async save(name: string, token: StoredToken): Promise<void> {\n await ensureDir();\n const path = tokenPath(name);\n await writeFile(path, JSON.stringify(token), { mode: OAUTH_TOKEN_FILE_MODE });\n // Ensure 0600 even when overwriting an existing file with broader permissions\n await chmod(path, OAUTH_TOKEN_FILE_MODE);\n },\n\n async load(name: string): Promise<StoredToken | null> {\n const path = tokenPath(name);\n try {\n const data = await readFile(path, 'utf-8');\n return JSON.parse(data) as StoredToken;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw new OAuthError(`Failed to read token: ${err instanceof Error ? err.message : String(err)}`);\n }\n },\n\n async remove(name: string): Promise<void> {\n const path = tokenPath(name);\n try {\n await unlink(path);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return; // Idempotent\n }\n throw new OAuthError(`Failed to remove token: ${err instanceof Error ? err.message : String(err)}`);\n }\n },\n\n async list(): Promise<string[]> {\n try {\n const files = await readdir(tokenDir);\n return files\n .filter((f) => f.endsWith('.json'))\n .map((f) => f.replace(/\\.json$/, ''));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw new OAuthError(`Failed to list tokens: ${err instanceof Error ? err.message : String(err)}`);\n }\n },\n };\n}\n","import type Database from 'better-sqlite3-multiple-ciphers';\nimport { createAuditStore, type AuditLogRow, type AuditFilters } from './store.js';\n\n/**\n * Query audit logs directly from SQLite (for CLI use).\n * Delegates to AuditStore.query() to avoid duplicating query logic.\n */\nexport function queryAuditLogs(db: Database.Database, filters: AuditFilters): AuditLogRow[] {\n const store = createAuditStore(db);\n return store.query(filters);\n}\n\nexport function formatAuditRow(row: AuditLogRow): string {\n const status = row.allowed ? '\\x1b[32mALLOW\\x1b[0m' : '\\x1b[31mBLOCK\\x1b[0m';\n const blockInfo = row.blocked_by ? ` [${row.blocked_by}: ${row.block_reason}]` : '';\n const tool = row.tool_or_resource ? ` → ${row.tool_or_resource}` : '';\n const latency = row.latency_ms !== null ? ` (${row.latency_ms.toFixed(1)}ms)` : '';\n\n return `${row.timestamp} ${status} ${row.identity_username}@${row.server} ${row.method}${tool}${blockInfo}${latency}`;\n}\n","import * as oauth from 'oauth4webapi';\nimport { createServer, type Server } from 'node:http';\nimport { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_TIMEOUT } from '../constants.js';\nimport { OAuthError } from '../errors.js';\n\nexport interface OAuthFlowOptions {\n issuer: string;\n clientId: string;\n clientSecret?: string;\n scopes: string[];\n callbackPort?: number;\n}\n\nexport interface OAuthFlowResult {\n access_token: string;\n refresh_token?: string;\n id_token?: string;\n expires_at: number;\n scope: string;\n}\n\nexport async function executeOAuthFlow(options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n const callbackPort = options.callbackPort ?? OAUTH_CALLBACK_PORT;\n const redirectUri = `http://127.0.0.1:${callbackPort}/callback`;\n\n // 1. Discover OpenID configuration\n const issuerUrl = new URL(options.issuer);\n const discoveryResponse = await oauth.discoveryRequest(issuerUrl);\n const authServer = await oauth.processDiscoveryResponse(issuerUrl, discoveryResponse);\n\n if (!authServer.authorization_endpoint) {\n throw new OAuthError('OAuth provider missing authorization_endpoint');\n }\n if (!authServer.token_endpoint) {\n throw new OAuthError('OAuth provider missing token_endpoint');\n }\n\n // 2. Generate PKCE verifier\n const codeVerifier = oauth.generateRandomCodeVerifier();\n const codeChallenge = await oauth.calculatePKCECodeChallenge(codeVerifier);\n\n // 3. Build authorization URL\n const authUrl = new URL(authServer.authorization_endpoint);\n authUrl.searchParams.set('client_id', options.clientId);\n authUrl.searchParams.set('redirect_uri', redirectUri);\n authUrl.searchParams.set('response_type', 'code');\n authUrl.searchParams.set('scope', options.scopes.join(' '));\n authUrl.searchParams.set('code_challenge', codeChallenge);\n authUrl.searchParams.set('code_challenge_method', 'S256');\n\n const state = oauth.generateRandomState();\n authUrl.searchParams.set('state', state);\n\n // 4. Start callback server and wait for authorization code URL params\n const callbackParams = await waitForCallback(callbackPort, authUrl.toString());\n\n // 5. Validate callback params and extract authorization code\n const client: oauth.Client = { client_id: options.clientId };\n const validatedParams = oauth.validateAuthResponse(authServer, client, callbackParams, state);\n\n // 6. Exchange code for tokens\n const clientAuth = options.clientSecret\n ? oauth.ClientSecretPost(options.clientSecret)\n : oauth.None();\n\n const tokenResponse = await oauth.authorizationCodeGrantRequest(\n authServer,\n client,\n clientAuth,\n validatedParams,\n redirectUri,\n codeVerifier,\n );\n\n const result = await oauth.processAuthorizationCodeResponse(authServer, client, tokenResponse);\n\n const expiresIn = result.expires_in ?? 3600;\n const expiresAt = Math.floor(Date.now() / 1000) + expiresIn;\n\n return {\n access_token: result.access_token,\n refresh_token: result.refresh_token,\n id_token: result.id_token,\n expires_at: expiresAt,\n scope: result.scope ?? options.scopes.join(' '),\n };\n}\n\nexport async function refreshOAuthToken(\n issuer: string,\n clientId: string,\n refreshToken: string,\n clientSecret?: string,\n): Promise<OAuthFlowResult> {\n const issuerUrl = new URL(issuer);\n const discoveryResponse = await oauth.discoveryRequest(issuerUrl);\n const authServer = await oauth.processDiscoveryResponse(issuerUrl, discoveryResponse);\n\n const client: oauth.Client = { client_id: clientId };\n const clientAuth = clientSecret\n ? oauth.ClientSecretPost(clientSecret)\n : oauth.None();\n\n const tokenResponse = await oauth.refreshTokenGrantRequest(\n authServer,\n client,\n clientAuth,\n refreshToken,\n );\n\n const result = await oauth.processRefreshTokenResponse(authServer, client, tokenResponse);\n\n const expiresIn = result.expires_in ?? 3600;\n const expiresAt = Math.floor(Date.now() / 1000) + expiresIn;\n\n return {\n access_token: result.access_token,\n refresh_token: result.refresh_token ?? refreshToken,\n id_token: result.id_token,\n expires_at: expiresAt,\n scope: result.scope ?? '',\n };\n}\n\nasync function waitForCallback(\n port: number,\n authUrl: string,\n): Promise<URLSearchParams> {\n return new Promise((resolve, reject) => {\n const server: Server = createServer((req, res) => {\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n\n if (url.pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const error = url.searchParams.get('error');\n if (error) {\n const desc = url.searchParams.get('error_description') ?? error;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Authentication Failed</h1><p>You can close this window.</p></body></html>');\n clearTimeout(timeout);\n server.close();\n reject(new OAuthError(`OAuth authorization failed: ${desc}`));\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Authentication Successful</h1><p>You can close this window.</p></body></html>');\n clearTimeout(timeout);\n server.close();\n resolve(url.searchParams);\n });\n\n server.listen(port, '127.0.0.1', () => {\n openBrowser(authUrl).catch(() => {\n console.log(`\\nOpen this URL in your browser to authenticate:\\n\\n ${authUrl}\\n`);\n });\n });\n\n const timeout = setTimeout(() => {\n server.close();\n reject(new OAuthError('OAuth flow timed out — no authorization callback received'));\n }, OAUTH_CALLBACK_TIMEOUT);\n });\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const execFileAsync = promisify(execFile);\n\n const platform = process.platform;\n if (platform === 'darwin') {\n await execFileAsync('open', [url]);\n } else if (platform === 'linux') {\n await execFileAsync('xdg-open', [url]);\n } else if (platform === 'win32') {\n await execFileAsync('cmd', ['/c', 'start', '', url]);\n } else {\n throw new Error(`Unsupported platform: ${platform}`);\n }\n}\n","import { readFile, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir, platform } from 'node:os';\nimport type { Command } from 'commander';\nimport yaml from 'js-yaml';\nimport { configSchema } from '../config/schema.js';\n\ninterface DiscoveredServer {\n name: string;\n command: string;\n args: string[];\n env: Record<string, string>;\n source: string;\n}\n\ninterface ClientConfig {\n name: string;\n paths: string[];\n serverKey: string;\n}\n\nfunction getClientConfigs(): ClientConfig[] {\n const home = homedir();\n const os = platform();\n\n const configs: ClientConfig[] = [];\n\n // Claude Desktop\n if (os === 'darwin') {\n configs.push({\n name: 'claude-desktop',\n paths: [join(home, 'Library/Application Support/Claude/claude_desktop_config.json')],\n serverKey: 'mcpServers',\n });\n } else if (os === 'win32') {\n const appData = process.env.APPDATA ?? join(home, 'AppData/Roaming');\n configs.push({\n name: 'claude-desktop',\n paths: [join(appData, 'Claude/claude_desktop_config.json')],\n serverKey: 'mcpServers',\n });\n }\n\n // Claude Code\n configs.push({\n name: 'claude-code',\n paths: [\n join(home, '.claude.json'),\n join(home, '.config/claude/settings.json'),\n ],\n serverKey: 'mcpServers',\n });\n\n // Cursor\n configs.push({\n name: 'cursor',\n paths: [\n join(home, '.cursor/mcp.json'),\n join(home, '.config/cursor/mcp.json'),\n ],\n serverKey: 'mcpServers',\n });\n\n // VS Code (Copilot)\n configs.push({\n name: 'vscode',\n paths: [\n join(home, '.vscode/mcp.json'),\n ],\n serverKey: 'servers',\n });\n\n // Windsurf\n configs.push({\n name: 'windsurf',\n paths: [\n join(home, '.codeium/windsurf/mcp_config.json'),\n ],\n serverKey: 'mcpServers',\n });\n\n return configs;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction extractServers(\n data: Record<string, unknown>,\n serverKey: string,\n source: string,\n): DiscoveredServer[] {\n const serversObj = data[serverKey] as Record<string, Record<string, unknown>> | undefined;\n if (!serversObj || typeof serversObj !== 'object') return [];\n\n const servers: DiscoveredServer[] = [];\n\n for (const [name, config] of Object.entries(serversObj)) {\n if (!config || typeof config !== 'object') continue;\n\n const command = typeof config.command === 'string' ? config.command : undefined;\n if (!command) continue;\n\n const args = Array.isArray(config.args)\n ? config.args.filter((a): a is string => typeof a === 'string')\n : [];\n\n const env: Record<string, string> = {};\n if (config.env && typeof config.env === 'object') {\n for (const [k, v] of Object.entries(config.env as Record<string, unknown>)) {\n if (typeof v === 'string') {\n // Emit env var reference instead of raw secret value\n env[k] = `\\${${k}}`;\n }\n }\n }\n\n servers.push({ name, command, args, env, source });\n }\n\n return servers;\n}\n\nfunction deduplicateServers(servers: DiscoveredServer[]): DiscoveredServer[] {\n const seen = new Map<string, DiscoveredServer>();\n\n for (const server of servers) {\n // Include env keys in dedup key so servers with different env configs aren't merged\n const envKey = Object.keys(server.env).sort().join(',');\n const key = `${server.command}:${server.args.join(',')}:${envKey}`;\n if (!seen.has(key)) {\n seen.set(key, server);\n }\n }\n\n return [...seen.values()];\n}\n\nfunction generateConfig(servers: DiscoveredServer[]): string {\n const serversObj: Record<string, Record<string, unknown>> = {};\n\n for (const server of servers) {\n const entry: Record<string, unknown> = {\n transport: 'stdio',\n command: server.command,\n args: server.args,\n };\n if (Object.keys(server.env).length > 0) {\n entry.env = server.env;\n }\n serversObj[server.name] = entry;\n }\n\n const config = {\n servers: serversObj,\n daemon: {\n log_level: 'info',\n },\n };\n\n return yaml.dump(config, { lineWidth: 120, quotingType: '\"', forceQuotes: false });\n}\n\nfunction generateInstructions(servers: DiscoveredServer[]): string {\n const lines: string[] = [\n '',\n 'To use MCP-Guard, update your MCP client config to route servers through the proxy:',\n '',\n ];\n\n const serverNames = [...new Set(servers.map((s) => s.name))];\n\n for (const name of serverNames) {\n lines.push(` \"${name}\": {`);\n lines.push(` \"command\": \"mcp-guard\",`);\n lines.push(` \"args\": [\"connect\", \"--server\", \"${name}\"]`);\n lines.push(` }`);\n lines.push('');\n }\n\n lines.push('The daemon auto-starts on first connection.');\n\n return lines.join('\\n');\n}\n\nexport interface InitOptions {\n output: string;\n dryRun?: boolean;\n client?: string;\n}\n\nexport async function runInit(opts: InitOptions): Promise<void> {\n const clientConfigs = getClientConfigs();\n\n const toScan = opts.client\n ? clientConfigs.filter((c) => c.name === opts.client)\n : clientConfigs;\n\n if (opts.client && toScan.length === 0) {\n const validClients = clientConfigs.map((c) => c.name).join(', ');\n console.error(`Unknown client: ${opts.client}. Valid clients: ${validClients}`);\n process.exit(1);\n }\n\n const allServers: DiscoveredServer[] = [];\n\n for (const client of toScan) {\n for (const configPath of client.paths) {\n if (!(await fileExists(configPath))) continue;\n\n try {\n const content = await readFile(configPath, 'utf-8');\n const data = JSON.parse(content) as Record<string, unknown>;\n const servers = extractServers(data, client.serverKey, client.name);\n if (servers.length > 0) {\n console.log(`Found ${servers.length} server(s) in ${client.name} (${configPath})`);\n allServers.push(...servers);\n }\n } catch (err) {\n console.warn(`Skipping ${configPath}: ${err instanceof SyntaxError ? 'invalid JSON' : err}`);\n }\n }\n }\n\n if (allServers.length === 0) {\n console.log('No MCP server configurations found.');\n console.log('');\n console.log('Looked in:');\n for (const client of toScan) {\n for (const p of client.paths) {\n console.log(` ${client.name}: ${p}`);\n }\n }\n console.log('');\n console.log('You can create a config manually — see mcp-guard.example.yaml');\n return;\n }\n\n const deduplicated = deduplicateServers(allServers);\n const yamlContent = generateConfig(deduplicated);\n\n // Validate generated config passes Zod schema\n const parsed = yaml.load(yamlContent);\n const validation = configSchema.safeParse(parsed);\n if (!validation.success) {\n console.error('Generated config failed validation (this is a bug):');\n for (const issue of validation.error.issues) {\n console.error(` ${issue.path.join('.')}: ${issue.message}`);\n }\n process.exit(1);\n }\n\n if (opts.dryRun) {\n console.log('---');\n process.stdout.write(yamlContent);\n } else {\n await writeFile(opts.output, yamlContent, 'utf-8');\n console.log(`Config written to ${opts.output}`);\n }\n\n console.log(generateInstructions(deduplicated));\n}\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Generate mcp-guard.yaml from existing MCP client configs')\n .option('-o, --output <path>', 'Output path', 'mcp-guard.yaml')\n .option('--dry-run', 'Print config to stdout instead of writing')\n .option('--client <name>', 'Only scan a specific client (claude-desktop, claude-code, cursor, vscode, windsurf)')\n .action(async (opts: { output: string; dryRun?: boolean; client?: string }) => {\n try {\n await runInit(opts);\n } catch (err) {\n console.error(`Failed to initialize: ${err}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":["join","yaml","readFile","join","merged","readFile","unlink","join","mkdir","writeFile","join","readFile","writeFile","mkdir","chmodSync","logger","chmodSync","logger","logger","logger","logger","logger","durationMs","timingSafeEqual","createHash","createHash","timingSafeEqual","logger","logger","createServer","randomBytes","timingSafeEqual","writeFile","join","join","dirname","status","logger","randomBytes","createServer","join","writeFile","timingSafeEqual","logger","join","mkdir","writeFile","connect","writeFramed","fileURLToPath","dirname","join","readFile","writeFile","unlink","mkdir","chmod","join","loadConfig","connect","createServer","createServer","platform","readFile","writeFile","join","homedir","yaml","program","fork","join","readFile","unlink"]}