@mgsoftwarebv/mg-dashboard-mcp 6.8.0 → 7.0.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.
- package/dist/index.js +31 -7987
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/proxy-mode.ts","../src/db-ssh-tunnel.ts","../../db/src/client.ts","../src/mijnhost-fetch.ts","../src/repo-tools.ts","../src/trigger-tools.ts","../src/index.ts"],"names":["args","proxyUrl","apiKey","Client","expandHome","join","existsSync","connectSsh","SshClient","readFileSync","server","createServer","dnsLookup","tlsConnect","author","sshExec","sql","getServerConnection","name","runId","instance","waitArg","waitSeconds","getArg","runProxyMode","fetchRemoteEnvValue","openDbSshTunnel","runProcess","spawn","sections","statSync","db","serverName","lines","content","conn","proxy","elapsed","r","text","ok","cmd","sqlText","output","footer","stageIds","Server","ListToolsRequestSchema","CallToolRequestSchema","createHttpServer","StdioServerTransport"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Proxy-mode entry point for the MG dashboard MCP package.\r\n *\r\n * Usage:\r\n * npx @mgsoftwarebv/mg-dashboard-mcp \\\r\n * --proxy-url=https://mg-mcp.mgsoftware.nl/v1/{INSTANCE_ID}/mcp \\\r\n * --api-key=pk_xxx \\\r\n * --ssh-key=$HOME/.ssh/id_ed25519\r\n *\r\n * What it does:\r\n * 1. At startup it does an SSH-key challenge handshake against the proxy\r\n * (POST /v1/auth/ssh/challenge → ssh-keygen -Y sign → POST\r\n * /v1/auth/ssh/verify) and obtains a short-lived `pks_xxx` bearer.\r\n * 2. It then runs as a stdio MCP server, transparently forwarding every\r\n * JSON-RPC message to/from the upstream proxy URL using\r\n * `StreamableHTTPClientTransport` with the bearer attached.\r\n * 3. Before the token expires it re-runs the handshake and swaps in the\r\n * fresh bearer without dropping the connection.\r\n *\r\n * This lets a user point Cursor's mcp.json at the local stdio command with\r\n * both factors: a static `pk_` proxy key plus a linked SSH key proof. The\r\n * static key is only sent during the SSH verify step; normal MCP traffic uses\r\n * the short-lived `pks_` session token.\r\n */\r\n\r\nimport { spawn } from \"node:child_process\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\r\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport {\r\n CallToolRequestSchema,\r\n CallToolResultSchema,\r\n EmptyResultSchema,\r\n GetPromptRequestSchema,\r\n GetPromptResultSchema,\r\n ListPromptsRequestSchema,\r\n ListPromptsResultSchema,\r\n ListResourcesRequestSchema,\r\n ListResourcesResultSchema,\r\n ListResourceTemplatesRequestSchema,\r\n ListResourceTemplatesResultSchema,\r\n ListToolsRequestSchema,\r\n ListToolsResultSchema,\r\n ReadResourceRequestSchema,\r\n ReadResourceResultSchema,\r\n SubscribeRequestSchema,\r\n UnsubscribeRequestSchema,\r\n} from \"@modelcontextprotocol/sdk/types.js\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction getArg(args: string[], name: string): string | undefined {\r\n return args.find((a) => a.startsWith(`--${name}=`))?.split(\"=\").slice(1).join(\"=\");\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePubkeyPath(input: string): { pubPath: string; pubText: string } {\r\n const candidate = expandHome(input);\r\n let pubPath: string;\r\n if (candidate.endsWith(\".pub\")) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = readFileSync(pubPath, \"utf8\").trim();\r\n if (!pubText) throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n return { pubPath, pubText };\r\n}\r\n\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n child.stdout.on(\"data\", (d) => {\r\n stdout += d.toString();\r\n });\r\n child.stderr.on(\"data\", (d) => {\r\n stderr += d.toString();\r\n });\r\n child.on(\"error\", (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on(\"close\", (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key handshake against /v1/auth/ssh/challenge + /v1/auth/ssh/verify\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface HandshakeResult {\r\n token: string;\r\n expiresAt: number; // ms epoch\r\n proxyKeyName: string;\r\n}\r\n\r\nfunction deriveAuthBaseUrl(proxyUrl: string): string {\r\n // proxyUrl looks like https://host/v1/{instanceId}/mcp\r\n // We need to call https://host (base) then /v1/auth/ssh/{challenge|verify}.\r\n const u = new URL(proxyUrl);\r\n return `${u.protocol}//${u.host}`;\r\n}\r\n\r\nasync function performHandshake(\r\n proxyUrl: string,\r\n apiKey: string,\r\n pubPath: string,\r\n pubText: string,\r\n): Promise<HandshakeResult> {\r\n const base = deriveAuthBaseUrl(proxyUrl);\r\n\r\n const challengeRes = await fetch(`${base}/v1/auth/ssh/challenge`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: \"{}\",\r\n });\r\n if (!challengeRes.ok) {\r\n const txt = await challengeRes.text().catch(() => \"\");\r\n throw new Error(`Challenge request failed (${challengeRes.status}): ${txt}`);\r\n }\r\n const challenge = (await challengeRes.json()) as {\r\n challenge_id: string;\r\n nonce: string;\r\n namespace: string;\r\n };\r\n\r\n const sign = await runProcess(\r\n \"ssh-keygen\",\r\n [\"-Y\", \"sign\", \"-f\", pubPath, \"-n\", challenge.namespace, \"-q\"],\r\n { stdin: challenge.nonce },\r\n );\r\n if (sign.code !== 0 || !sign.stdout.includes(\"BEGIN SSH SIGNATURE\")) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${sign.code}). Make sure ssh-agent is running ` +\r\n `and has the matching private key loaded. stderr: ${sign.stderr.trim() || \"(empty)\"}`,\r\n );\r\n }\r\n\r\n const verifyRes = await fetch(`${base}/v1/auth/ssh/verify`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n challenge_id: challenge.challenge_id,\r\n api_key: apiKey,\r\n pubkey: pubText,\r\n signature: sign.stdout,\r\n }),\r\n });\r\n if (!verifyRes.ok) {\r\n const txt = await verifyRes.text().catch(() => \"\");\r\n throw new Error(`Verify request failed (${verifyRes.status}): ${txt}`);\r\n }\r\n const verified = (await verifyRes.json()) as {\r\n token: string;\r\n expires_in_seconds: number;\r\n proxy_key_name: string;\r\n };\r\n\r\n return {\r\n token: verified.token,\r\n expiresAt: Date.now() + verified.expires_in_seconds * 1000,\r\n proxyKeyName: verified.proxy_key_name,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bidirectional message forwarding\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Bridge between a stdio MCP server (talking to e.g. Cursor) and a remote\r\n * Streamable-HTTP MCP server (the proxy). Each incoming JSON-RPC message\r\n * is forwarded verbatim, and responses / notifications stream back.\r\n */\r\nasync function runBridge(handshake: HandshakeResult, proxyUrl: string, refresh: () => Promise<HandshakeResult>) {\r\n let currentToken = handshake.token;\r\n const requestHeaders: Record<string, string> = {\r\n Authorization: `Bearer ${currentToken}`,\r\n };\r\n\r\n const upstreamTransport = new StreamableHTTPClientTransport(new URL(proxyUrl), {\r\n requestInit: { headers: requestHeaders },\r\n });\r\n const upstream = new Client({ name: \"mg-dashboard-mcp-proxy-bridge\", version: \"1.0.0\" });\r\n\r\n // Schedule a refresh 2 minutes before expiry.\r\n const scheduleRefresh = (result: HandshakeResult) => {\r\n const msUntilRefresh = Math.max(30_000, result.expiresAt - Date.now() - 120_000);\r\n setTimeout(async () => {\r\n try {\r\n const fresh = await refresh();\r\n currentToken = fresh.token;\r\n requestHeaders.Authorization = `Bearer ${currentToken}`;\r\n console.error(`[Proxy] Token refreshed (key: ${fresh.proxyKeyName})`);\r\n scheduleRefresh(fresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Token refresh failed: ${err instanceof Error ? err.message : String(err)}`);\r\n // Try again sooner on failure.\r\n setTimeout(() => scheduleRefresh({ ...result, expiresAt: Date.now() + 60_000 }), 30_000);\r\n }\r\n }, msUntilRefresh).unref();\r\n };\r\n scheduleRefresh(handshake);\r\n\r\n // Server-side stdio transport faces Cursor.\r\n const stdioServer = new Server(\r\n { name: \"mg-dashboard-mcp-proxy\", version: \"1.0.0\" },\r\n { capabilities: { tools: {}, prompts: {}, resources: {}, logging: {} } },\r\n );\r\n\r\n const forwardRequest =\r\n (resultSchema: Parameters<typeof upstream.request>[1]) =>\r\n async (request: unknown) =>\r\n upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n resultSchema,\r\n );\r\n\r\n // Explicitly forward first-class MCP methods. The SDK fallback only covers\r\n // truly unknown methods; Cursor's standard discovery calls need registered\r\n // handlers or the client sees an empty server.\r\n stdioServer.setRequestHandler(\r\n ListToolsRequestSchema,\r\n forwardRequest(ListToolsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n CallToolRequestSchema,\r\n forwardRequest(CallToolResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListPromptsRequestSchema,\r\n forwardRequest(ListPromptsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n GetPromptRequestSchema,\r\n forwardRequest(GetPromptResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourcesRequestSchema,\r\n forwardRequest(ListResourcesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ReadResourceRequestSchema,\r\n forwardRequest(ReadResourceResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourceTemplatesRequestSchema,\r\n forwardRequest(ListResourceTemplatesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n SubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n UnsubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n\r\n // Dumb forwarder: any request from Cursor → forward to upstream → return result.\r\n stdioServer.fallbackRequestHandler = async (request: unknown) => {\r\n return await upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n // We don't care about the schema check on the way through — let the\r\n // upstream's actual response flow back unmodified.\r\n undefined as unknown as Parameters<typeof upstream.request>[1],\r\n );\r\n };\r\n // Same for notifications.\r\n stdioServer.fallbackNotificationHandler = async (notification: unknown) => {\r\n await upstream.notification(notification as Parameters<typeof upstream.notification>[0]);\r\n };\r\n\r\n await upstream.connect(upstreamTransport);\r\n\r\n // Forward upstream notifications back to Cursor.\r\n upstream.fallbackNotificationHandler = async (notification: unknown) => {\r\n await stdioServer.notification(notification as Parameters<typeof stdioServer.notification>[0]);\r\n };\r\n\r\n await stdioServer.connect(new StdioServerTransport());\r\n console.error(`[Proxy] Bridge ready. Forwarding stdio → ${proxyUrl}`);\r\n\r\n // In proxy mode this function is the long-lived process. Some SDK transports\r\n // finish their async `connect()` setup without leaving an obvious foreground\r\n // handle behind, which can make Node exit immediately after \"Bridge ready\".\r\n // Keep the process alive until Cursor closes stdin or the process receives a\r\n // termination signal.\r\n await new Promise<void>((resolve) => {\r\n const keepAlive = setInterval(() => undefined, 2_147_483_647);\r\n const done = () => {\r\n clearInterval(keepAlive);\r\n resolve();\r\n };\r\n process.stdin.once(\"close\", done);\r\n process.stdin.once(\"end\", done);\r\n process.once(\"SIGINT\", done);\r\n process.once(\"SIGTERM\", done);\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function runProxyMode(args: string[]): Promise<void> {\r\n const proxyUrl = getArg(args, \"proxy-url\") || process.env.MG_DASHBOARD_PROXY_URL;\r\n const apiKey = getArg(args, \"api-key\") || process.env.MG_DASHBOARD_API_KEY;\r\n const sshKey = getArg(args, \"ssh-key\") || process.env.MG_DASHBOARD_SSH_KEY;\r\n\r\n if (!proxyUrl) {\r\n console.error(\"--proxy-url is required (or set MG_DASHBOARD_PROXY_URL)\");\r\n process.exit(1);\r\n }\r\n if (!apiKey) {\r\n console.error(\"--api-key is required in proxy mode (or set MG_DASHBOARD_API_KEY)\");\r\n process.exit(1);\r\n }\r\n if (!sshKey) {\r\n console.error(\"--ssh-key is required in proxy mode (or set MG_DASHBOARD_SSH_KEY)\");\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Starting in proxy-bridge mode → ${proxyUrl}`);\r\n\r\n let resolved: { pubPath: string; pubText: string };\r\n try {\r\n resolved = resolvePubkeyPath(sshKey);\r\n } catch (err) {\r\n console.error(`[Proxy] ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n const refresh = () => performHandshake(proxyUrl, apiKey, resolved.pubPath, resolved.pubText);\r\n\r\n let handshake: HandshakeResult;\r\n try {\r\n handshake = await refresh();\r\n } catch (err) {\r\n console.error(`[Proxy] Handshake failed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Authenticated as \"${handshake.proxyKeyName}\"`);\r\n console.error(`[Proxy] Token valid for ${Math.floor((handshake.expiresAt - Date.now()) / 60000)} min`);\r\n\r\n try {\r\n await runBridge(handshake, proxyUrl, refresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Bridge crashed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * Opens an SSH-key-authenticated TCP forward to the remote Postgres host and\r\n * rewrites the database URL to hit the local listener. Used when the production\r\n * Postgres port is firewalled and only reachable from inside the host that the\r\n * MCP user already has SSH access to.\r\n *\r\n * Reuses the same SSH key the MCP already uses for proxy-mode auth, so the\r\n * trust model is unchanged: holding the key = ability to reach the DB.\r\n */\r\n\r\nimport { createServer, type AddressInfo, type Server, type Socket } from \"node:net\";\r\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\nimport { Client as SshClient, type ClientChannel } from \"ssh2\";\r\n\r\nexport interface DbSshTunnelOptions {\r\n /** \"user@host[:port]\" target for the SSH connection. */\r\n sshTarget: string;\r\n /** Path to the SSH private key (or its `.pub`; we'll find the private one). */\r\n sshKeyPath: string;\r\n /** Original Postgres URL (host/port get rewritten to the local listener). */\r\n databaseUrl: string;\r\n /** Optional override for the SSH keepalive interval (ms). Default 30s. */\r\n keepaliveIntervalMs?: number;\r\n}\r\n\r\nexport interface DbSshTunnel {\r\n /** New URL pointing at 127.0.0.1:<localPort>, same path/credentials/query. */\r\n rewrittenDatabaseUrl: string;\r\n /** Local TCP port the rewritten URL points at. */\r\n localPort: number;\r\n /** Closes the tunnel and SSH connection. */\r\n close(): Promise<void>;\r\n}\r\n\r\nexport interface FetchRemoteEnvOptions {\r\n sshTarget: string;\r\n sshKeyPath: string;\r\n /** Absolute path to the .env file on the remote host. */\r\n remoteEnvPath: string;\r\n /** Which key to extract (default: DATABASE_PRIMARY_URL). */\r\n envKey?: string;\r\n keepaliveIntervalMs?: number;\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePrivateKeyPath(input: string): string {\r\n const candidate = expandHome(input);\r\n const stripped = candidate.endsWith(\".pub\") ? candidate.slice(0, -4) : candidate;\r\n if (existsSync(stripped) && statSync(stripped).isFile()) return stripped;\r\n throw new Error(\r\n `SSH private key not found at ${stripped}. The --db-ssh-tunnel flag needs the private key (not just .pub) to open the tunnel.`,\r\n );\r\n}\r\n\r\nfunction parseSshTarget(target: string): { username: string; host: string; port: number } {\r\n const at = target.indexOf(\"@\");\r\n if (at === -1) {\r\n throw new Error(`--db-ssh-tunnel must be in the form user@host[:port], got: ${target}`);\r\n }\r\n const username = target.slice(0, at);\r\n const hostPart = target.slice(at + 1);\r\n const colon = hostPart.lastIndexOf(\":\");\r\n if (colon === -1) return { username, host: hostPart, port: 22 };\r\n const port = Number(hostPart.slice(colon + 1));\r\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\r\n throw new Error(`Invalid SSH port in --db-ssh-tunnel: ${hostPart.slice(colon + 1)}`);\r\n }\r\n return { username, host: hostPart.slice(0, colon), port };\r\n}\r\n\r\nfunction rewriteUrl(originalUrl: string, localPort: number): string {\r\n const parsed = new URL(originalUrl);\r\n parsed.hostname = \"127.0.0.1\";\r\n parsed.port = String(localPort);\r\n return parsed.toString();\r\n}\r\n\r\nasync function connectSsh(opts: {\r\n host: string;\r\n port: number;\r\n username: string;\r\n privateKey: Buffer;\r\n keepaliveIntervalMs: number;\r\n}): Promise<SshClient> {\r\n return await new Promise((resolve, reject) => {\r\n const conn = new SshClient();\r\n const onError = (err: Error) => {\r\n conn.removeAllListeners();\r\n reject(err);\r\n };\r\n conn.once(\"ready\", () => {\r\n conn.removeListener(\"error\", onError);\r\n resolve(conn);\r\n });\r\n conn.once(\"error\", onError);\r\n conn.connect({\r\n host: opts.host,\r\n port: opts.port,\r\n username: opts.username,\r\n privateKey: opts.privateKey,\r\n keepaliveInterval: opts.keepaliveIntervalMs,\r\n keepaliveCountMax: 3,\r\n readyTimeout: 20_000,\r\n });\r\n });\r\n}\r\n\r\nfunction execOverSsh(conn: SshClient, cmd: string): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve, reject) => {\r\n conn.exec(cmd, (err, stream) => {\r\n if (err) {\r\n reject(err);\r\n return;\r\n }\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n stream.on(\"data\", (chunk: Buffer) => {\r\n stdout += chunk.toString(\"utf8\");\r\n });\r\n stream.stderr.on(\"data\", (chunk: Buffer) => {\r\n stderr += chunk.toString(\"utf8\");\r\n });\r\n stream.on(\"close\", (code: number) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n });\r\n });\r\n}\r\n\r\nfunction parseEnvValue(content: string, key: string): string | undefined {\r\n const re = new RegExp(`^${key}\\\\s*=\\\\s*(.*)$`, \"m\");\r\n const m = content.match(re);\r\n if (!m || !m[1]) return undefined;\r\n let value = m[1].trim();\r\n if (value.length >= 2 && (value[0] === '\"' || value[0] === \"'\") && value[value.length - 1] === value[0]) {\r\n value = value.slice(1, -1);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Connects via SSH and reads a single env var from a remote .env file.\r\n * Useful so mcp.json never has to hold the DB password — the MCP fetches it\r\n * fresh at startup from the same trusted host the tunnel terminates on.\r\n */\r\nexport async function fetchRemoteEnvValue(options: FetchRemoteEnvOptions): Promise<string> {\r\n const { username, host, port } = parseSshTarget(options.sshTarget);\r\n const privateKeyPath = resolvePrivateKeyPath(options.sshKeyPath);\r\n const privateKey = readFileSync(privateKeyPath);\r\n const keepaliveIntervalMs = options.keepaliveIntervalMs ?? 30_000;\r\n const envKey = options.envKey ?? \"DATABASE_PRIMARY_URL\";\r\n\r\n const conn = await connectSsh({ host, port, username, privateKey, keepaliveIntervalMs });\r\n try {\r\n const safePath = options.remoteEnvPath.replace(/'/g, \"'\\\\''\");\r\n const result = await execOverSsh(conn, `cat -- '${safePath}'`);\r\n if (result.code !== 0) {\r\n throw new Error(\r\n `remote cat ${options.remoteEnvPath} failed (exit ${result.code}): ${result.stderr.trim()}`,\r\n );\r\n }\r\n const value = parseEnvValue(result.stdout, envKey);\r\n if (!value) {\r\n throw new Error(`${envKey} not found in ${options.remoteEnvPath}`);\r\n }\r\n return value;\r\n } finally {\r\n conn.end();\r\n }\r\n}\r\n\r\nexport async function openDbSshTunnel(options: DbSshTunnelOptions): Promise<DbSshTunnel> {\r\n const { username, host, port } = parseSshTarget(options.sshTarget);\r\n const privateKeyPath = resolvePrivateKeyPath(options.sshKeyPath);\r\n const privateKey = readFileSync(privateKeyPath);\r\n const keepaliveIntervalMs = options.keepaliveIntervalMs ?? 30_000;\r\n\r\n const parsedDbUrl = new URL(options.databaseUrl);\r\n const remoteHost = parsedDbUrl.hostname;\r\n const remotePort = Number(parsedDbUrl.port || \"5432\");\r\n\r\n const conn = await connectSsh({ host, port, username, privateKey, keepaliveIntervalMs });\r\n conn.on(\"error\", (err) => {\r\n console.error(`[mcp][db-ssh-tunnel] ssh connection error: ${err.message}`);\r\n });\r\n conn.on(\"close\", () => {\r\n console.error(\"[mcp][db-ssh-tunnel] ssh connection closed; MCP will exit so Cursor can respawn it\");\r\n process.exit(1);\r\n });\r\n\r\n const server: Server = createServer((local: Socket) => {\r\n conn.forwardOut(\"127.0.0.1\", 0, remoteHost, remotePort, (err: Error | undefined, stream: ClientChannel) => {\r\n if (err) {\r\n console.error(`[mcp][db-ssh-tunnel] forwardOut failed: ${err.message}`);\r\n local.destroy(err);\r\n return;\r\n }\r\n local.on(\"error\", () => stream.destroy());\r\n stream.on(\"error\", () => local.destroy());\r\n local.pipe(stream).pipe(local);\r\n });\r\n });\r\n\r\n const localPort = await new Promise<number>((resolve, reject) => {\r\n server.once(\"error\", reject);\r\n server.listen(0, \"127.0.0.1\", () => {\r\n const addr = server.address() as AddressInfo | null;\r\n if (!addr || typeof addr === \"string\") {\r\n reject(new Error(\"Failed to bind local tunnel listener\"));\r\n return;\r\n }\r\n resolve(addr.port);\r\n });\r\n });\r\n\r\n const rewrittenDatabaseUrl = rewriteUrl(options.databaseUrl, localPort);\r\n console.error(\r\n `[mcp][db-ssh-tunnel] forwarding 127.0.0.1:${localPort} -> ${remoteHost}:${remotePort} via ssh ${username}@${host}:${port}`,\r\n );\r\n\r\n return {\r\n rewrittenDatabaseUrl,\r\n localPort,\r\n async close() {\r\n await new Promise<void>((resolve) => server.close(() => resolve()));\r\n conn.end();\r\n },\r\n };\r\n}\r\n","/**\r\n * Postgres connection + Drizzle client for mg-dashboard.\r\n *\r\n * Single-region, single-pool. Reads `DATABASE_PRIMARY_URL` (or\r\n * `DATABASE_PRIMARY_POOLER_URL` if you put a pooler in front later).\r\n */\r\n\r\nimport { drizzle } from \"drizzle-orm/postgres-js\";\r\nimport postgres from \"postgres\";\r\n\r\nconst connectionConfig: postgres.Options<Record<string, never>> = {\r\n prepare: false,\r\n idle_timeout: 20,\r\n max_lifetime: 60 * 60,\r\n connect_timeout: 30,\r\n max: 10,\r\n onnotice: (notice) => {\r\n if (notice.severity !== \"INFO\") {\r\n console.warn(\"[mg-dashboard db]\", notice.message);\r\n }\r\n },\r\n connection: {\r\n application_name: `mg-dashboard-${process.env.TRIGGER_RUN_ID ? \"trigger\" : \"local\"}`,\r\n },\r\n};\r\n\r\nfunction getDatabaseUrl(): string {\r\n const url =\r\n process.env.DATABASE_PRIMARY_POOLER_URL || process.env.DATABASE_PRIMARY_URL;\r\n if (!url) {\r\n throw new Error(\r\n \"[@mgboiler/db] DATABASE_PRIMARY_URL or DATABASE_PRIMARY_POOLER_URL must be set\",\r\n );\r\n }\r\n return url;\r\n}\r\n\r\nlet _pool: postgres.Sql | null = null;\r\nlet _db: ReturnType<typeof drizzle> | null = null;\r\n\r\n/** Lazy: only opens the pool when the first call lands (test-friendly). */\r\nfunction getPool(): postgres.Sql {\r\n if (!_pool) {\r\n _pool = postgres(getDatabaseUrl(), connectionConfig);\r\n }\r\n return _pool;\r\n}\r\n\r\n/**\r\n * Pooled Drizzle client. Use everywhere except for `LISTEN`-style\r\n * connection-scoped operations (those use `createDedicatedConnection`).\r\n */\r\nexport function getDb() {\r\n if (!_db) {\r\n _db = drizzle(getPool(), { casing: \"snake_case\" });\r\n }\r\n return _db;\r\n}\r\n\r\nexport type Database = ReturnType<typeof getDb>;\r\n\r\n/**\r\n * Dedicated single-connection postgres.js client for `LISTEN`-style flows.\r\n *\r\n * Important: never released back to a pool — would lose the LISTEN\r\n * registration on connection churn. Caller owns the lifecycle.\r\n */\r\nexport function createDedicatedConnection(applicationName: string): postgres.Sql {\r\n return postgres(getDatabaseUrl(), {\r\n max: 1,\r\n idle_timeout: 0,\r\n max_lifetime: null,\r\n connection: { application_name: applicationName },\r\n });\r\n}\r\n\r\n/** Test/teardown helper — closes the pool. Not used in normal runtime. */\r\nexport async function closeDb(): Promise<void> {\r\n if (_pool) {\r\n await _pool.end({ timeout: 5 });\r\n _pool = null;\r\n _db = null;\r\n }\r\n}\r\n","/**\r\n * HTTPS fetch to mijn.host routed through the MG SSH proxy so outbound API\r\n * calls use the proxy's whitelisted IP (same trust model as ProxyJump SSH).\r\n */\r\n\r\nimport { once } from 'node:events';\r\nimport { lookup as dnsLookup } from 'node:dns/promises';\r\nimport { connect as tlsConnect } from 'node:tls';\r\nimport { Client as SshClient, type ClientChannel } from 'ssh2';\r\n\r\nexport interface SshOutboundProxyOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\nexport interface FetchViaSshProxyOptions {\r\n proxy: SshOutboundProxyOptions;\r\n url: string;\r\n method?: string;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport interface FetchViaSshProxyResult {\r\n status: number;\r\n statusText: string;\r\n body: string;\r\n}\r\n\r\nfunction connectSsh(opts: SshOutboundProxyOptions): Promise<SshClient> {\r\n return new Promise((resolve, reject) => {\r\n const client = new SshClient();\r\n client.once('ready', () => resolve(client));\r\n client.once('error', reject);\r\n client.connect({\r\n host: opts.hostname,\r\n port: opts.port,\r\n username: opts.username,\r\n password: opts.password,\r\n privateKey: opts.privateKey,\r\n passphrase: opts.passphrase,\r\n readyTimeout: opts.timeout ?? 30_000,\r\n });\r\n });\r\n}\r\n\r\nfunction forwardOut(client: SshClient, host: string, port: number): Promise<ClientChannel> {\r\n return new Promise((resolve, reject) => {\r\n client.forwardOut('127.0.0.1', 0, host, port, (err, stream) => {\r\n if (err) reject(err);\r\n else resolve(stream);\r\n });\r\n });\r\n}\r\n\r\n/** Perform one HTTPS request to `url` via SSH `forwardOut` + TLS. */\r\nexport async function fetchViaSshProxy(\r\n options: FetchViaSshProxyOptions,\r\n): Promise<FetchViaSshProxyResult> {\r\n const parsedUrl = new URL(options.url);\r\n if (parsedUrl.protocol !== 'https:') {\r\n throw new Error(`fetchViaSshProxy only supports https URLs, got ${parsedUrl.protocol}`);\r\n }\r\n\r\n const targetHost = parsedUrl.hostname;\r\n const targetPort = parsedUrl.port ? Number(parsedUrl.port) : 443;\r\n const method = options.method ?? 'GET';\r\n const body = options.body ?? '';\r\n const headers: Record<string, string> = { ...options.headers };\r\n if (body && !headers['Content-Length']) {\r\n headers['Content-Length'] = String(Buffer.byteLength(body));\r\n }\r\n headers.Host = parsedUrl.host;\r\n\r\n const ssh = await connectSsh(options.proxy);\r\n const timeoutMs = options.timeoutMs ?? 60_000;\r\n let timer: ReturnType<typeof setTimeout> | undefined;\r\n\r\n try {\r\n // Force IPv4 resolution so we exit the proxy over its whitelisted IPv4\r\n // address. The SSH proxy is dual-stack and `forwardOut` would otherwise\r\n // let the remote server resolve the hostname — which on Linux prefers\r\n // AAAA, and mijn.host's API key is only whitelisted for the IPv4 egress.\r\n let connectHost = targetHost;\r\n try {\r\n const resolved = await dnsLookup(targetHost, { family: 4 });\r\n connectHost = resolved.address;\r\n } catch {\r\n // Fall back to letting the proxy resolve. TLS SNI + Host header still\r\n // use the original hostname, so this only affects which A/AAAA record\r\n // gets dialed.\r\n }\r\n\r\n const stream = await forwardOut(ssh, connectHost, targetPort);\r\n const tlsSocket = tlsConnect({\r\n socket: stream,\r\n servername: targetHost,\r\n ALPNProtocols: ['http/1.1'],\r\n });\r\n\r\n await Promise.race([\r\n once(tlsSocket, 'secureConnect'),\r\n new Promise<never>((_, reject) => {\r\n timer = setTimeout(\r\n () => reject(new Error(`mijn.host fetch via SSH proxy timed out after ${timeoutMs}ms`)),\r\n timeoutMs,\r\n );\r\n }),\r\n ]);\r\n if (timer) clearTimeout(timer);\r\n\r\n // Write the HTTP/1.1 request manually onto the already-TLS socket. We\r\n // can't use `https.request({ createConnection })` because Node's https\r\n // agent honours `createConnection` inconsistently and may open its own\r\n // direct TCP socket to `targetHost`, bypassing the SSH tunnel.\r\n const requestPath = `${parsedUrl.pathname || '/'}${parsedUrl.search}`;\r\n const headerLines = [`${method} ${requestPath} HTTP/1.1`];\r\n if (!('Connection' in headers)) headers.Connection = 'close';\r\n for (const [k, v] of Object.entries(headers)) headerLines.push(`${k}: ${v}`);\r\n headerLines.push('', '');\r\n tlsSocket.write(headerLines.join('\\r\\n'));\r\n if (body) tlsSocket.write(body);\r\n\r\n return await new Promise<FetchViaSshProxyResult>((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n const onError = (err: Error) => {\r\n tlsSocket.removeAllListeners();\r\n reject(err);\r\n };\r\n tlsSocket.on('data', (chunk: Buffer) => chunks.push(chunk));\r\n tlsSocket.on('end', () => {\r\n const raw = Buffer.concat(chunks);\r\n const headerEnd = raw.indexOf('\\r\\n\\r\\n');\r\n if (headerEnd === -1) return reject(new Error('mijn.host response missing headers'));\r\n const headerBlob = raw.slice(0, headerEnd).toString('utf8');\r\n const [statusLine, ...headerLinesIn] = headerBlob.split('\\r\\n');\r\n const statusMatch = statusLine?.match(/^HTTP\\/\\d\\.\\d (\\d{3}) ?(.*)$/);\r\n if (!statusMatch) return reject(new Error(`Invalid status line: ${statusLine}`));\r\n const status = Number(statusMatch[1]);\r\n const statusText = statusMatch[2] ?? '';\r\n\r\n let bodyBuf = raw.slice(headerEnd + 4);\r\n const transferEnc = headerLinesIn\r\n .find((l) => /^transfer-encoding:/i.test(l))\r\n ?.split(':')[1]\r\n ?.trim()\r\n .toLowerCase();\r\n if (transferEnc === 'chunked') {\r\n const decoded: Buffer[] = [];\r\n let i = 0;\r\n while (i < bodyBuf.length) {\r\n const lineEnd = bodyBuf.indexOf('\\r\\n', i);\r\n if (lineEnd === -1) break;\r\n const size = parseInt(bodyBuf.slice(i, lineEnd).toString('ascii'), 16);\r\n if (!Number.isFinite(size) || size <= 0) break;\r\n i = lineEnd + 2;\r\n decoded.push(bodyBuf.slice(i, i + size));\r\n i += size + 2;\r\n }\r\n bodyBuf = Buffer.concat(decoded);\r\n }\r\n\r\n resolve({ status, statusText, body: bodyBuf.toString('utf8') });\r\n });\r\n tlsSocket.on('error', onError);\r\n });\r\n } finally {\r\n if (timer) clearTimeout(timer);\r\n ssh.end();\r\n }\r\n}\r\n","/**\n * Repo reference MCP tools.\n *\n * Read-only tools for navigating a curated set of GitHub repositories.\n * All operations run via SSH against the central \"mcp-repo-host\" server,\n * which keeps shallow clones in /srv/mcp-repos/<org>/<repo>. The clones\n * are populated and kept up to date by the discover-repositories and\n * sync-repository-clones Trigger.dev tasks; this module never writes.\n *\n * Tools (all gated behind the `repositories` module permission):\n * - repo-list list registered repositories (enabled / all)\n * - repo-tree list files at a path / ref (git ls-tree)\n * - repo-read read a file (git show <ref>:<path>) with offset/length\n * - repo-search ripgrep across one or more enabled repos\n * - repo-find-symbol ripgrep with language-aware definition presets\n * - repo-log git log of a path / branch\n * - repo-blame git blame for a line range\n *\n * @module repo-tools\n */\n\nimport type { Database } from \"@mgboiler/db/client\";\nimport { sql } from \"drizzle-orm\";\n\n// ---------------------------------------------------------------------------\n// Types mirrored from index.ts to avoid circular imports\n// ---------------------------------------------------------------------------\n\ninterface SshConnectionOptions {\n hostname: string;\n port: number;\n username: string;\n password?: string;\n privateKey?: string;\n passphrase?: string;\n timeout?: number;\n}\n\ninterface SshResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\ntype SshExecFn = (\n conn: SshConnectionOptions,\n command: string,\n proxy?: SshConnectionOptions,\n) => Promise<SshResult>;\n\ntype GetServerConnectionFn = (\n serverId: string,\n) => Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions }>;\n\ninterface ToolResult {\n [key: string]: unknown;\n content: { type: string; text: string }[];\n}\n\nexport interface RepoToolDeps {\n db: Database;\n sshExec: SshExecFn;\n getServerConnection: GetServerConnectionFn;\n}\n\n// ---------------------------------------------------------------------------\n// Tool definitions\n// ---------------------------------------------------------------------------\n\nexport const REPO_TOOLS = [\n {\n name: \"repo-list\",\n description:\n \"List registered reference repositories. Auto-discovered from configured GitHub orgs; each row carries an `enabled` flag — only enabled repos are clonable on the mcp-repo-host and reachable via the other repo-* tools. Filter with `enabledOnly` (default true), `org`, `topic`, or `search` (substring on full_name / description).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n enabledOnly: {\n type: \"boolean\",\n description:\n \"When true (default), only return repos with enabled = true.\",\n },\n org: { type: \"string\", description: \"Filter by org/owner login.\" },\n topic: {\n type: \"string\",\n description: \"Match against the repo's GitHub topics array.\",\n },\n search: {\n type: \"string\",\n description:\n \"Substring match (case-insensitive) on full_name or description.\",\n },\n limit: {\n type: \"number\",\n description: \"Max rows to return (default 200, cap 1000).\",\n },\n },\n },\n },\n {\n name: \"repo-tree\",\n description:\n \"List entries (files + directories) inside a repository at an optional path and ref. Uses `git ls-tree` on the central clone — no network round-trip to GitHub.\\n\\n\" +\n 'Identify the repo by `repo` (full_name like \"MGSoftwareBV/mg-dashboard\" or just the short name when unambiguous). `path` is the subdirectory to list (default repo root). `ref` accepts a branch, tag or SHA (default HEAD).\\n\\n' +\n \"Use `recursive: true` to walk into subdirectories; use `pattern` (glob on basename) to keep output focused (e.g. `*.tsx`). Output is bounded — pass `maxResults` to raise the cap (default 2000).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n repo: {\n type: \"string\",\n description:\n 'Repo full_name (e.g. \"MGSoftwareBV/mg-dashboard\") or short name.',\n },\n path: {\n type: \"string\",\n description: \"Subdirectory inside the repo (default: repo root).\",\n },\n ref: {\n type: \"string\",\n description:\n \"Branch, tag or commit SHA (default: HEAD aka default branch).\",\n },\n recursive: {\n type: \"boolean\",\n description: \"Walk into subdirectories (default false).\",\n },\n pattern: {\n type: \"string\",\n description: \"Glob filter on basename (e.g. `*.ts`).\",\n },\n maxResults: {\n type: \"number\",\n description: \"Max entries to return (default 2000, cap 20000).\",\n },\n },\n required: [\"repo\"],\n },\n },\n {\n name: \"repo-read\",\n description:\n \"Read a single text file from a repository at an optional ref. Uses `git show <ref>:<path>` so any branch / tag / commit works — not just the current checkout.\\n\\n\" +\n \"Identify the repo by full_name or short name. Capped at 1 MiB inline; use `offset` and/or `length` for ranged reads. Ranged reads include a `# range: bytes A-B of TOTAL` header so the caller knows what window they got.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n repo: { type: \"string\", description: \"Repo full_name or short name.\" },\n path: {\n type: \"string\",\n description: \"File path inside the repo (relative to repo root).\",\n },\n ref: {\n type: \"string\",\n description: \"Branch, tag or commit SHA (default: HEAD).\",\n },\n offset: {\n type: \"number\",\n description:\n \"Byte offset to start reading (0-indexed). Triggers ranged-read mode.\",\n },\n length: {\n type: \"number\",\n description:\n \"Bytes to read (cap 1 MiB). Defaults to remaining-from-offset.\",\n },\n },\n required: [\"repo\", \"path\"],\n },\n },\n {\n name: \"repo-search\",\n description:\n \"ripgrep across one or more enabled repositories. Returns matching lines with file + line number, grouped by file.\\n\\n\" +\n \"Scope: pass `repo` for a single repo or `repos: [...]` for fan-out across multiple. Omit both to search every enabled repo (capped for safety).\\n\\n\" +\n \"`pattern` is a regex (PCRE-lite ripgrep syntax). Toggle `caseSensitive` (default smart-case). Use `glob` to limit by filename (e.g. `*.tsx`), `path` to scope to a subdirectory, `context` for ±N lines, and `maxResults` to cap output (default 200 matches).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n pattern: {\n type: \"string\",\n description: \"Regex to search for (ripgrep syntax).\",\n },\n repo: {\n type: \"string\",\n description: \"Single repo full_name or short name.\",\n },\n repos: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Multiple repos (mutually exclusive with `repo`).\",\n },\n path: {\n type: \"string\",\n description: \"Subdirectory inside each repo to scope the search.\",\n },\n glob: {\n type: \"string\",\n description: \"Filename glob filter (e.g. `*.ts`).\",\n },\n caseSensitive: {\n type: \"boolean\",\n description: \"When true, force case-sensitive (default: smart-case).\",\n },\n context: {\n type: \"number\",\n description: \"Show ±N context lines per match (default 0, cap 5).\",\n },\n maxResults: {\n type: \"number\",\n description:\n \"Cap total matches across all repos (default 200, cap 2000).\",\n },\n },\n required: [\"pattern\"],\n },\n },\n {\n name: \"repo-find-symbol\",\n description:\n \"Locate the definition of a symbol (class / function / type / const) across one or more repos using language-aware regex presets layered on top of ripgrep. Faster and less noisy than a plain repo-search when you know the exact identifier.\\n\\n\" +\n \"Presets cover TypeScript / JavaScript, Go, Python, Rust, Java/Kotlin, C#, and PHP by default; pass `languages` to narrow (e.g. `['ts','php']`). Scope with `repo` / `repos` like repo-search.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n symbol: {\n type: \"string\",\n description: \"Exact identifier to find (no regex metacharacters).\",\n },\n repo: {\n type: \"string\",\n description: \"Single repo full_name or short name.\",\n },\n repos: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Multiple repos (mutually exclusive with `repo`).\",\n },\n languages: {\n type: \"array\",\n items: {\n type: \"string\",\n enum: [\"ts\", \"js\", \"go\", \"py\", \"rs\", \"java\", \"cs\", \"php\"],\n },\n description:\n \"Restrict to one or more language presets. Defaults to all.\",\n },\n maxResults: {\n type: \"number\",\n description: \"Cap matches returned (default 50, cap 500).\",\n },\n },\n required: [\"symbol\"],\n },\n },\n {\n name: \"repo-log\",\n description:\n \"git log for a repository or path. Returns one row per commit: SHA, short author, ISO date, subject. Use `path` to follow history of a specific file/directory; `limit` to cap entries (default 25, max 500); optional `since` / `until` / `author` filters.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n repo: { type: \"string\", description: \"Repo full_name or short name.\" },\n path: {\n type: \"string\",\n description: \"Optional path filter (file or directory).\",\n },\n ref: {\n type: \"string\",\n description: \"Branch / tag / SHA to start from (default HEAD).\",\n },\n limit: {\n type: \"number\",\n description: \"Max commits to return (default 25, max 500).\",\n },\n since: {\n type: \"string\",\n description: \"ISO date or git relative date (e.g. `2 weeks ago`).\",\n },\n until: {\n type: \"string\",\n description: \"ISO date or git relative date.\",\n },\n author: {\n type: \"string\",\n description: \"Substring match on author name or email.\",\n },\n },\n required: [\"repo\"],\n },\n },\n {\n name: \"repo-blame\",\n description:\n \"git blame for a line range in a file. Returns `sha author iso-date line` rows so it's easy to spot when a specific line was introduced. Provide `path` and a `startLine`/`endLine` window (max 500 lines per call).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n repo: { type: \"string\", description: \"Repo full_name or short name.\" },\n path: { type: \"string\", description: \"File path inside the repo.\" },\n startLine: {\n type: \"number\",\n description: \"1-based start line (default 1).\",\n },\n endLine: {\n type: \"number\",\n description:\n \"1-based end line (default startLine + 200, capped at startLine + 500).\",\n },\n ref: {\n type: \"string\",\n description: \"Branch / tag / SHA to blame against (default HEAD).\",\n },\n },\n required: [\"repo\", \"path\"],\n },\n },\n];\n\nexport const REPO_TOOL_NAMES = new Set(REPO_TOOLS.map((t) => t.name));\n\nexport const REPO_TOOL_MODULE_MAP: Record<string, string> = {\n \"repo-list\": \"repositories\",\n \"repo-tree\": \"repositories\",\n \"repo-read\": \"repositories\",\n \"repo-search\": \"repositories\",\n \"repo-find-symbol\": \"repositories\",\n \"repo-log\": \"repositories\",\n \"repo-blame\": \"repositories\",\n};\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst READ_INLINE_LIMIT = 1024 * 1024; // 1 MiB\nconst SEARCH_DEFAULT_MAX = 200;\nconst SEARCH_HARD_CAP = 2000;\nconst TREE_DEFAULT_MAX = 2000;\nconst TREE_HARD_CAP = 20000;\nconst LOG_DEFAULT_MAX = 25;\nconst LOG_HARD_CAP = 500;\nconst BLAME_WINDOW_DEFAULT = 200;\nconst BLAME_WINDOW_MAX = 500;\nconst FAN_OUT_HARD_CAP = 20; // when neither repo nor repos[] given\n\n// Host lookup cache (60 s) — the same TTL we use for list-servers caching\n// so a Cursor session never pays the lookup latency more than once a minute.\ninterface HostCache {\n expiresAt: number;\n serverId: string;\n conn: SshConnectionOptions;\n proxy?: SshConnectionOptions;\n}\nlet hostCache: HostCache | null = null;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ninterface RepoRow extends Record<string, unknown> {\n id: string;\n org: string;\n name: string;\n full_name: string;\n default_branch: string;\n visibility: string;\n description: string | null;\n topics: string[] | null;\n enabled: boolean;\n clone_path: string | null;\n last_pulled_at: string | null;\n last_sync_error: string | null;\n}\n\ninterface SshServerIdRow extends Record<string, unknown> {\n id: string;\n}\n\nfunction bashQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/**\n * Resolve and decrypt the managed server tagged \"mcp-repo-host\". Cached\n * for 60 s. We use this instead of plumbing yet another serverId through\n * tool calls — the tag lookup keeps the central host transparent.\n */\nasync function resolveRepoHost(deps: RepoToolDeps): Promise<HostCache> {\n if (hostCache && hostCache.expiresAt > Date.now()) return hostCache;\n\n const rows = await deps.db.execute<SshServerIdRow>(sql`\n SELECT id\n FROM managed_server\n WHERE tags @> '[\"mcp-repo-host\"]'::jsonb\n LIMIT 2\n `);\n\n if (rows.length === 0) {\n throw new Error(\n 'No SSH server has the \"mcp-repo-host\" tag. Add the tag to exactly one server to enable repo-* tools.',\n );\n }\n const serverId = rows[0]!.id;\n const { conn, proxy } = await deps.getServerConnection(serverId);\n hostCache = {\n expiresAt: Date.now() + 60_000,\n serverId,\n conn,\n proxy,\n };\n return hostCache;\n}\n\n/**\n * Resolve a single `repo` input (full_name or short name) to a row that's\n * enabled AND has a clone_path. Throws with a helpful message otherwise.\n */\nasync function resolveRepo(\n deps: RepoToolDeps,\n repoInput: string,\n): Promise<RepoRow> {\n const trimmed = repoInput.trim();\n if (!trimmed) throw new Error(\"repo: empty input\");\n\n const isFullName = trimmed.includes(\"/\");\n const rows = isFullName\n ? await deps.db.execute<RepoRow>(sql`\n SELECT id, org, name, full_name, default_branch, visibility, description,\n topics, enabled, clone_path, last_pulled_at, last_sync_error\n FROM mcp_repositories\n WHERE enabled = true AND full_name = ${trimmed}\n LIMIT 5\n `)\n : await deps.db.execute<RepoRow>(sql`\n SELECT id, org, name, full_name, default_branch, visibility, description,\n topics, enabled, clone_path, last_pulled_at, last_sync_error\n FROM mcp_repositories\n WHERE enabled = true AND name = ${trimmed}\n LIMIT 5\n `);\n if (rows.length === 0) {\n throw new Error(\n `Repo \"${trimmed}\" is not enabled (or not registered). Enable it in the Repositories module first; the sync job will then clone it on the mcp-repo-host.`,\n );\n }\n if (rows.length > 1) {\n const options = rows.map((r) => r.full_name).join(\", \");\n throw new Error(\n `Ambiguous repo \"${trimmed}\". Pass the full_name. Candidates: ${options}`,\n );\n }\n const row = rows[0]!;\n if (!row.clone_path) {\n throw new Error(\n `Repo \"${row.full_name}\" is enabled but has not been cloned yet. Trigger sync-repository-clones or wait for the next scheduled run.`,\n );\n }\n return row;\n}\n\nasync function resolveRepos(\n deps: RepoToolDeps,\n args: { repo?: string; repos?: string[] },\n): Promise<RepoRow[]> {\n if (args.repo) {\n return [await resolveRepo(deps, args.repo)];\n }\n if (args.repos && args.repos.length > 0) {\n const seen = new Set<string>();\n const out: RepoRow[] = [];\n for (const r of args.repos) {\n const row = await resolveRepo(deps, r);\n if (!seen.has(row.id)) {\n seen.add(row.id);\n out.push(row);\n }\n }\n return out;\n }\n // Fan-out: all enabled repos, capped.\n const rows = await deps.db.execute<RepoRow>(sql`\n SELECT id, org, name, full_name, default_branch, visibility, description,\n topics, enabled, clone_path, last_pulled_at, last_sync_error\n FROM mcp_repositories\n WHERE enabled = true AND clone_path IS NOT NULL\n ORDER BY full_name\n LIMIT ${FAN_OUT_HARD_CAP}\n `);\n return rows;\n}\n\nasync function runRemote(\n deps: RepoToolDeps,\n host: HostCache,\n script: string,\n timeoutMs = 60_000,\n): Promise<SshResult> {\n return deps.sshExec(\n { ...host.conn, timeout: timeoutMs },\n `bash -c ${bashQuote(script)}`,\n host.proxy,\n );\n}\n\nfunction clampInt(\n value: unknown,\n def: number,\n min: number,\n max: number,\n): number {\n const n = Number(value);\n if (!Number.isFinite(n)) return def;\n return Math.min(max, Math.max(min, Math.trunc(n)));\n}\n\nfunction basenameMatchesGlob(name: string, pattern: string): boolean {\n // Tiny glob: *, ?, literal — enough for repo-tree's basename filter. Heavy\n // filtering happens server-side via git ls-tree + grep where possible.\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\");\n const re = new RegExp(`^${escaped}$`, \"i\");\n return re.test(name);\n}\n\n// ---------------------------------------------------------------------------\n// repo-list\n// ---------------------------------------------------------------------------\n\nasync function handleRepoList(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const enabledOnly = args.enabledOnly !== false;\n const limit = clampInt(args.limit, 200, 1, 1000);\n const search =\n typeof args.search === \"string\" ? args.search.trim().toLowerCase() : \"\";\n const orgFilter = typeof args.org === \"string\" ? args.org.trim() : \"\";\n const topicFilter = typeof args.topic === \"string\" ? args.topic.trim() : \"\";\n\n const conds = [sql`TRUE`];\n if (enabledOnly) conds.push(sql`enabled = true`);\n if (orgFilter) conds.push(sql`org = ${orgFilter}`);\n if (topicFilter) conds.push(sql`topics @> ARRAY[${topicFilter}]::text[]`);\n const where = sql.join(conds, sql` AND `);\n\n const rowsRaw = await deps.db.execute<RepoRow>(sql`\n SELECT id, org, name, full_name, default_branch, visibility, description,\n topics, enabled, clone_path, last_pulled_at, last_sync_error\n FROM mcp_repositories\n WHERE ${where}\n ORDER BY full_name\n LIMIT ${limit}\n `);\n\n let rows: RepoRow[] = [...rowsRaw];\n if (search) {\n rows = rows.filter((r) => {\n const a = r.full_name.toLowerCase();\n const b = (r.description || \"\").toLowerCase();\n return a.includes(search) || b.includes(search);\n });\n }\n\n if (rows.length === 0) {\n const hint = enabledOnly\n ? \"No enabled repositories match. Pass enabledOnly: false to also see disabled rows, or run discover-repositories first.\"\n : \"No repositories registered. Run the discover-repositories task to populate this table.\";\n return { content: [{ type: \"text\", text: hint }] };\n }\n\n const header = `${\"FULL_NAME\".padEnd(45)} ${\"BRANCH\".padEnd(15)} ${\"VIS\".padEnd(8)} ${\"ENABLED\".padEnd(8)} ${\"LAST_PULLED\".padEnd(20)} CLONE_PATH`;\n const lines = rows.map((r) => {\n const pulled = r.last_pulled_at\n ? new Date(r.last_pulled_at).toISOString().slice(0, 19).replace(\"T\", \" \")\n : \"never\";\n const err = r.last_sync_error\n ? ` ERR:${r.last_sync_error.slice(0, 40)}`\n : \"\";\n return `${r.full_name.padEnd(45)} ${(r.default_branch || \"\").padEnd(15)} ${(r.visibility || \"\").padEnd(8)} ${(r.enabled ? \"yes\" : \"no\").padEnd(8)} ${pulled.padEnd(20)} ${r.clone_path || \"-\"}${err}`;\n });\n return {\n content: [\n {\n type: \"text\",\n text: `${header}\\n${\"-\".repeat(header.length)}\\n${lines.join(\"\\n\")}`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// repo-tree\n// ---------------------------------------------------------------------------\n\nasync function handleRepoTree(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const row = await resolveRepo(deps, String(args.repo || \"\"));\n const host = await resolveRepoHost(deps);\n const ref =\n typeof args.ref === \"string\" && args.ref ? args.ref : row.default_branch;\n const path =\n typeof args.path === \"string\" ? args.path.replace(/^\\/+|\\/+$/g, \"\") : \"\";\n const recursive = args.recursive === true;\n const maxResults = clampInt(\n args.maxResults,\n TREE_DEFAULT_MAX,\n 1,\n TREE_HARD_CAP,\n );\n const pattern = typeof args.pattern === \"string\" ? args.pattern : \"\";\n\n // -r recurses; --name-only just gives paths; -l adds size. We pipe to head\n // for the cap. Output format we render ourselves below.\n const lsArgs = recursive ? \"-r\" : \"\";\n const refSpec = path ? `${ref}:${bashQuote(path)}` : bashQuote(ref);\n const cmd = `git -C ${bashQuote(row.clone_path!)} ls-tree ${lsArgs} --long ${refSpec} 2>&1 | head -n ${maxResults + 1}`;\n\n const res = await runRemote(deps, host, cmd, 30_000);\n if (res.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${(res.stderr || res.stdout || \"git ls-tree failed\").trim().slice(0, 500)}`,\n },\n ],\n };\n }\n\n // ls-tree --long: <mode> SP <type> SP <object> SP <size>|\"-\" TAB <path>\n const lines: {\n mode: string;\n type: string;\n object: string;\n size: string;\n path: string;\n }[] = [];\n for (const raw of res.stdout.split(\"\\n\")) {\n const line = raw.trimEnd();\n if (!line) continue;\n const tabIdx = line.indexOf(\"\\t\");\n if (tabIdx === -1) continue;\n const left = line.slice(0, tabIdx).trim().split(/\\s+/);\n const entryPath = line.slice(tabIdx + 1);\n if (left.length < 4) continue;\n const [mode, type, object, size] = [left[0]!, left[1]!, left[2]!, left[3]!];\n if (pattern) {\n const base = entryPath.split(\"/\").pop() || entryPath;\n if (!basenameMatchesGlob(base, pattern)) continue;\n }\n lines.push({ mode, type, object, size, path: entryPath });\n if (lines.length >= maxResults) break;\n }\n\n if (lines.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No entries at ${row.full_name}@${ref}${path ? `:${path}` : \"\"}`,\n },\n ],\n };\n }\n\n const header = `${\"TYPE\".padEnd(6)} ${\"SIZE\".padEnd(10)} ${\"OBJECT\".padEnd(12)} PATH`;\n const rendered = lines.map((e) => {\n const size = e.type === \"blob\" ? e.size : \"-\";\n return `${e.type.padEnd(6)} ${size.padEnd(10)} ${e.object.slice(0, 12).padEnd(12)} ${e.path}`;\n });\n const footer =\n lines.length >= maxResults\n ? `\\n\\n[truncated at ${maxResults} entries — pass maxResults to widen]`\n : \"\";\n return {\n content: [\n {\n type: \"text\",\n text: `repo: ${row.full_name} ref: ${ref}${path ? ` path: ${path}` : \"\"}\\n${header}\\n${\"-\".repeat(header.length)}\\n${rendered.join(\"\\n\")}${footer}`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// repo-read\n// ---------------------------------------------------------------------------\n\nasync function handleRepoRead(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const row = await resolveRepo(deps, String(args.repo || \"\"));\n const host = await resolveRepoHost(deps);\n const filePath = String(args.path || \"\").replace(/^\\/+/, \"\");\n if (!filePath)\n return { content: [{ type: \"text\", text: \"Error: path is required\" }] };\n const ref =\n typeof args.ref === \"string\" && args.ref ? args.ref : row.default_branch;\n\n const ranged = args.offset !== undefined || args.length !== undefined;\n const offset = clampInt(args.offset, 0, 0, Number.MAX_SAFE_INTEGER);\n const length = clampInt(args.length, READ_INLINE_LIMIT, 1, READ_INLINE_LIMIT);\n\n // We want the total size for the range header, even when ranged. Two\n // commands chained: first prints \"<size>\\n\" then the (possibly ranged)\n // content. We separate them with a sentinel line.\n const SENTINEL = \"__MCP_REPO_READ_BODY__\";\n const refSpec = `${ref}:${filePath}`;\n let body: string;\n if (ranged) {\n body = `git -C ${bashQuote(row.clone_path!)} show ${bashQuote(refSpec)} | tail -c +${offset + 1} | head -c ${length}`;\n } else {\n body = `git -C ${bashQuote(row.clone_path!)} show ${bashQuote(refSpec)} | head -c ${READ_INLINE_LIMIT}`;\n }\n const cmd = `set -o pipefail; SZ=$(git -C ${bashQuote(row.clone_path!)} cat-file -s ${bashQuote(refSpec)}) && echo \"$SZ\" && echo \"${SENTINEL}\" && ${body}`;\n\n const res = await runRemote(deps, host, cmd, 60_000);\n if (res.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${(res.stderr || res.stdout || \"git show failed\").trim().slice(0, 500)}`,\n },\n ],\n };\n }\n const idx = res.stdout.indexOf(`${SENTINEL}\\n`);\n if (idx === -1) {\n return {\n content: [\n { type: \"text\", text: `Error: malformed output reading ${filePath}` },\n ],\n };\n }\n const totalSize = Number(res.stdout.slice(0, idx).trim());\n const content = res.stdout.slice(idx + SENTINEL.length + 1);\n\n if (ranged) {\n const end = Math.min(totalSize, offset + length) - 1;\n const header = `# range: bytes ${offset}-${end} of ${totalSize}\\n`;\n return { content: [{ type: \"text\", text: header + content }] };\n }\n if (totalSize > READ_INLINE_LIMIT) {\n const header = `# truncated: showing first ${READ_INLINE_LIMIT} bytes of ${totalSize} — use offset/length for ranged reads\\n`;\n return { content: [{ type: \"text\", text: header + content }] };\n }\n return { content: [{ type: \"text\", text: content }] };\n}\n\n// ---------------------------------------------------------------------------\n// repo-search (ripgrep on the central host)\n// ---------------------------------------------------------------------------\n\nasync function handleRepoSearch(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const pattern = String(args.pattern || \"\");\n if (!pattern)\n return { content: [{ type: \"text\", text: \"Error: pattern is required\" }] };\n\n const rows = await resolveRepos(deps, {\n repo: typeof args.repo === \"string\" ? args.repo : undefined,\n repos: Array.isArray(args.repos)\n ? (args.repos as unknown[]).map(String)\n : undefined,\n });\n if (rows.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No enabled, cloned repositories available to search.\",\n },\n ],\n };\n }\n\n const host = await resolveRepoHost(deps);\n const path =\n typeof args.path === \"string\" ? args.path.replace(/^\\/+|\\/+$/g, \"\") : \"\";\n const glob = typeof args.glob === \"string\" ? args.glob : \"\";\n const caseSensitive = args.caseSensitive === true;\n const context = clampInt(args.context, 0, 0, 5);\n const cap = clampInt(args.maxResults, SEARCH_DEFAULT_MAX, 1, SEARCH_HARD_CAP);\n\n const rgFlags = [\n \"--with-filename\",\n \"--line-number\",\n \"--color=never\",\n caseSensitive ? \"\" : \"--smart-case\",\n context > 0 ? `-C ${context}` : \"\",\n glob ? `--glob ${bashQuote(glob)}` : \"\",\n `--max-count ${Math.min(cap, 200)}`,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const sections: string[] = [];\n let remaining = cap;\n for (const row of rows) {\n if (remaining <= 0) break;\n const target = path\n ? `${row.clone_path}/${path}`\n : (row.clone_path as string);\n // -m caps matches per file; we already cap --max-count above. We rely on\n // an outer head to enforce the global cap inexpensively.\n const cmd = `rg ${rgFlags} -e ${bashQuote(pattern)} ${bashQuote(target)} 2>&1 | head -n ${remaining * (context * 2 + 1) + 200}`;\n const res = await runRemote(deps, host, cmd, 60_000);\n // rg returns 1 when no match — that's not an error for us.\n if (res.exitCode !== 0 && res.exitCode !== 1) {\n sections.push(\n `=== ${row.full_name} ===\\nError: ${(res.stderr || res.stdout || \"rg failed\").trim().slice(0, 300)}`,\n );\n continue;\n }\n const body = res.stdout.trim();\n if (!body) {\n sections.push(`=== ${row.full_name} ===\\n(no matches)`);\n continue;\n }\n // Strip the clone_path prefix so output stays repo-relative.\n const prefix = `${row.clone_path}/`;\n const cleaned = body\n .split(\"\\n\")\n .map((l) => (l.startsWith(prefix) ? l.slice(prefix.length) : l))\n .join(\"\\n\");\n // Count match lines (ones that aren't context separators) for the cap.\n const matchLines = cleaned\n .split(\"\\n\")\n .filter((l) => /:\\d+:/.test(l)).length;\n remaining -= matchLines;\n sections.push(`=== ${row.full_name} ===\\n${cleaned}`);\n }\n\n const footer =\n remaining <= 0\n ? `\\n\\n[hit cap of ${cap} matches across repos — narrow the pattern or pass maxResults]`\n : \"\";\n return { content: [{ type: \"text\", text: sections.join(\"\\n\\n\") + footer }] };\n}\n\n// ---------------------------------------------------------------------------\n// repo-find-symbol\n// ---------------------------------------------------------------------------\n\nconst SYMBOL_PRESETS: Record<\n string,\n { exts: string[]; pattern: (sym: string) => string }\n> = {\n ts: {\n exts: [\"ts\", \"tsx\"],\n pattern: (s) =>\n `(export\\\\s+(default\\\\s+)?)?(async\\\\s+)?(class|interface|type|enum|function|const|let|var)\\\\s+${s}\\\\b|\\\\b${s}\\\\s*[:=]\\\\s*(async\\\\s*)?\\\\(|^\\\\s*${s}\\\\s*\\\\(`,\n },\n js: {\n exts: [\"js\", \"jsx\", \"mjs\", \"cjs\"],\n pattern: (s) =>\n `(export\\\\s+(default\\\\s+)?)?(async\\\\s+)?(class|function|const|let|var)\\\\s+${s}\\\\b|\\\\b${s}\\\\s*[:=]\\\\s*(async\\\\s*)?\\\\(`,\n },\n go: {\n exts: [\"go\"],\n pattern: (s) =>\n `^func\\\\s+(\\\\([^)]*\\\\)\\\\s+)?${s}\\\\b|^type\\\\s+${s}\\\\b|^var\\\\s+${s}\\\\b|^const\\\\s+${s}\\\\b`,\n },\n py: {\n exts: [\"py\"],\n pattern: (s) => `^\\\\s*(async\\\\s+)?def\\\\s+${s}\\\\b|^\\\\s*class\\\\s+${s}\\\\b`,\n },\n rs: {\n exts: [\"rs\"],\n pattern: (s) => `\\\\b(fn|struct|enum|trait|type|const|static)\\\\s+${s}\\\\b`,\n },\n java: {\n exts: [\"java\", \"kt\"],\n pattern: (s) =>\n `(public|private|protected)?\\\\s*(static\\\\s+)?(class|interface|enum|record)\\\\s+${s}\\\\b|\\\\b\\\\w+\\\\s+${s}\\\\s*\\\\(`,\n },\n cs: {\n exts: [\"cs\"],\n pattern: (s) =>\n `(public|private|protected|internal)\\\\s+(static\\\\s+)?(class|interface|struct|enum|record)\\\\s+${s}\\\\b|\\\\b${s}\\\\s*\\\\(`,\n },\n php: {\n exts: [\"php\"],\n pattern: (s) =>\n `\\\\b(function|class|interface|trait)\\\\s+${s}\\\\b|\\\\bconst\\\\s+${s}\\\\b`,\n },\n};\n\nasync function handleRepoFindSymbol(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const symbol = String(args.symbol || \"\").trim();\n if (!symbol)\n return { content: [{ type: \"text\", text: \"Error: symbol is required\" }] };\n if (!/^[A-Za-z_$][\\w$]*$/.test(symbol)) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: symbol \"${symbol}\" must be a plain identifier (letters, digits, underscore, $). Use repo-search for regex matches.`,\n },\n ],\n };\n }\n\n const rows = await resolveRepos(deps, {\n repo: typeof args.repo === \"string\" ? args.repo : undefined,\n repos: Array.isArray(args.repos)\n ? (args.repos as unknown[]).map(String)\n : undefined,\n });\n if (rows.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No enabled, cloned repositories available to search.\",\n },\n ],\n };\n }\n\n const host = await resolveRepoHost(deps);\n const langs =\n Array.isArray(args.languages) && args.languages.length > 0\n ? (args.languages as unknown[])\n .map(String)\n .filter((l) => l in SYMBOL_PRESETS)\n : Object.keys(SYMBOL_PRESETS);\n const cap = clampInt(args.maxResults, 50, 1, 500);\n\n // Build one big alternation per repo so we ssh once per repo.\n const sections: string[] = [];\n let remaining = cap;\n for (const row of rows) {\n if (remaining <= 0) break;\n const perLang: string[] = [];\n const extGlobs: string[] = [];\n for (const lang of langs) {\n const preset = SYMBOL_PRESETS[lang]!;\n perLang.push(`(?:${preset.pattern(symbol)})`);\n for (const ext of preset.exts) extGlobs.push(`*.${ext}`);\n }\n const combined = perLang.join(\"|\");\n const globArgs = extGlobs.map((g) => `--glob ${bashQuote(g)}`).join(\" \");\n const cmd = `rg --with-filename --line-number --color=never --smart-case ${globArgs} -e ${bashQuote(combined)} ${bashQuote(row.clone_path!)} 2>&1 | head -n ${remaining * 2}`;\n const res = await runRemote(deps, host, cmd, 45_000);\n if (res.exitCode !== 0 && res.exitCode !== 1) {\n sections.push(\n `=== ${row.full_name} ===\\nError: ${(res.stderr || res.stdout || \"rg failed\").trim().slice(0, 300)}`,\n );\n continue;\n }\n const body = res.stdout.trim();\n if (!body) {\n sections.push(`=== ${row.full_name} ===\\n(no match for \"${symbol}\")`);\n continue;\n }\n const prefix = `${row.clone_path}/`;\n const cleaned = body\n .split(\"\\n\")\n .map((l) => (l.startsWith(prefix) ? l.slice(prefix.length) : l))\n .join(\"\\n\");\n const matchCount = cleaned.split(\"\\n\").length;\n remaining -= matchCount;\n sections.push(`=== ${row.full_name} ===\\n${cleaned}`);\n }\n\n const footer =\n remaining <= 0\n ? `\\n\\n[hit cap of ${cap} matches — pass maxResults to widen]`\n : \"\";\n return { content: [{ type: \"text\", text: sections.join(\"\\n\\n\") + footer }] };\n}\n\n// ---------------------------------------------------------------------------\n// repo-log\n// ---------------------------------------------------------------------------\n\nasync function handleRepoLog(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const row = await resolveRepo(deps, String(args.repo || \"\"));\n const host = await resolveRepoHost(deps);\n const limit = clampInt(args.limit, LOG_DEFAULT_MAX, 1, LOG_HARD_CAP);\n const ref =\n typeof args.ref === \"string\" && args.ref ? args.ref : row.default_branch;\n const path =\n typeof args.path === \"string\" ? args.path.replace(/^\\/+/, \"\") : \"\";\n const since = typeof args.since === \"string\" ? args.since : \"\";\n const until = typeof args.until === \"string\" ? args.until : \"\";\n const author = typeof args.author === \"string\" ? args.author : \"\";\n\n // Tab-delimited so we can keep parsing cheap; %x09 is a literal tab.\n const fmt = \"%H%x09%an%x09%aI%x09%s\";\n const optParts = [\n `-n ${limit}`,\n `--pretty=format:${fmt}`,\n since ? `--since=${bashQuote(since)}` : \"\",\n until ? `--until=${bashQuote(until)}` : \"\",\n author ? `--author=${bashQuote(author)}` : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n const refPart = bashQuote(ref);\n const pathPart = path ? ` -- ${bashQuote(path)}` : \"\";\n const cmd = `git -C ${bashQuote(row.clone_path!)} log ${optParts} ${refPart}${pathPart} 2>&1`;\n\n const res = await runRemote(deps, host, cmd, 45_000);\n if (res.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${(res.stderr || res.stdout || \"git log failed\").trim().slice(0, 500)}`,\n },\n ],\n };\n }\n const lines = res.stdout.trim().split(\"\\n\").filter(Boolean);\n if (lines.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No commits found for ${row.full_name}@${ref}${path ? `:${path}` : \"\"}`,\n },\n ],\n };\n }\n const rendered = lines.map((l) => {\n const parts = l.split(\"\\t\");\n const sha = (parts[0] || \"\").slice(0, 12);\n const author = parts[1] || \"\";\n const date = parts[2] || \"\";\n const subject = parts[3] || \"\";\n return `${sha.padEnd(12)} ${date.padEnd(25)} ${author.padEnd(25)} ${subject}`;\n });\n const header = `${\"SHA\".padEnd(12)} ${\"DATE\".padEnd(25)} ${\"AUTHOR\".padEnd(25)} SUBJECT`;\n return {\n content: [\n {\n type: \"text\",\n text: `${header}\\n${\"-\".repeat(header.length)}\\n${rendered.join(\"\\n\")}`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// repo-blame\n// ---------------------------------------------------------------------------\n\nasync function handleRepoBlame(\n deps: RepoToolDeps,\n args: Record<string, unknown>,\n): Promise<ToolResult> {\n const row = await resolveRepo(deps, String(args.repo || \"\"));\n const host = await resolveRepoHost(deps);\n const filePath = String(args.path || \"\").replace(/^\\/+/, \"\");\n if (!filePath)\n return { content: [{ type: \"text\", text: \"Error: path is required\" }] };\n const ref =\n typeof args.ref === \"string\" && args.ref ? args.ref : row.default_branch;\n const startLine = clampInt(args.startLine, 1, 1, Number.MAX_SAFE_INTEGER);\n const endLine = clampInt(\n args.endLine,\n startLine + BLAME_WINDOW_DEFAULT - 1,\n startLine,\n startLine + BLAME_WINDOW_MAX - 1,\n );\n\n const cmd = `git -C ${bashQuote(row.clone_path!)} blame --line-porcelain -L ${startLine},${endLine} ${bashQuote(ref)} -- ${bashQuote(filePath)} 2>&1`;\n const res = await runRemote(deps, host, cmd, 45_000);\n if (res.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${(res.stderr || res.stdout || \"git blame failed\").trim().slice(0, 500)}`,\n },\n ],\n };\n }\n\n // --line-porcelain emits one full header block per source line. Easy to\n // collapse into a compact `sha author iso-date line` row.\n const blocks = res.stdout.split(\"\\n\\t\");\n const out: string[] = [];\n for (const block of blocks) {\n const lines = block.split(\"\\n\");\n let sha = \"\";\n let author = \"\";\n let authorTime = \"\";\n let authorTz = \"\";\n let sourceLine = \"\";\n let inHeader = true;\n for (const raw of lines) {\n if (inHeader) {\n if (!sha) {\n const m = raw.match(/^([0-9a-f]{40})\\s/);\n if (m) {\n sha = m[1]!;\n continue;\n }\n }\n if (raw.startsWith(\"author \")) author = raw.slice(7);\n else if (raw.startsWith(\"author-time \")) authorTime = raw.slice(12);\n else if (raw.startsWith(\"author-tz \")) authorTz = raw.slice(10);\n else if (raw.startsWith(\"\\t\")) {\n sourceLine = raw.slice(1);\n inHeader = false;\n }\n } else {\n sourceLine += \"\\n\" + raw;\n }\n }\n if (!sha) continue;\n const date = authorTime\n ? new Date(Number(authorTime) * 1000).toISOString().slice(0, 19)\n : \"\";\n out.push(\n `${sha.slice(0, 12)} ${date}${authorTz ? \" \" + authorTz : \"\"} ${author.padEnd(25)} ${sourceLine}`,\n );\n }\n\n if (out.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No blame data for ${row.full_name}:${filePath} L${startLine}-${endLine}`,\n },\n ],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `repo: ${row.full_name} file: ${filePath} ref: ${ref} lines: ${startLine}-${endLine}\\n${out.join(\"\\n\")}`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Dispatcher\n// ---------------------------------------------------------------------------\n\nexport async function handleRepoTool(\n name: string,\n args: Record<string, unknown>,\n deps: RepoToolDeps,\n): Promise<ToolResult> {\n switch (name) {\n case \"repo-list\":\n return handleRepoList(deps, args);\n case \"repo-tree\":\n return handleRepoTree(deps, args);\n case \"repo-read\":\n return handleRepoRead(deps, args);\n case \"repo-search\":\n return handleRepoSearch(deps, args);\n case \"repo-find-symbol\":\n return handleRepoFindSymbol(deps, args);\n case \"repo-log\":\n return handleRepoLog(deps, args);\n case \"repo-blame\":\n return handleRepoBlame(deps, args);\n default:\n return {\n content: [{ type: \"text\", text: `Unknown repo tool: ${name}` }],\n };\n }\n}\n","/**\r\n * Trigger.dev MCP Tools\r\n *\r\n * SSH-based tools for managing Trigger.dev projects. All projects run on a\r\n * single Docker Compose instance. The compose project, server, postgres\r\n * container, and webapp port are auto-discovered — callers only need to\r\n * provide the Trigger.dev project slug (from trigger-list).\r\n *\r\n * @module trigger-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types (mirrored from index.ts to avoid circular imports)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\ntype SshExecFn = (\r\n conn: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n) => Promise<SshResult>;\r\n\r\ntype GetServerConnectionFn = (\r\n serverId: string,\r\n) => Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions }>;\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\ninterface TriggerToolDeps {\r\n sshExec: SshExecFn;\r\n getServerConnection: GetServerConnectionFn;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Trigger.dev API response shapes (partial, only fields we display)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerRunItem {\r\n id: string;\r\n status: string;\r\n taskIdentifier: string;\r\n version?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n startedAt?: string;\r\n finishedAt?: string;\r\n durationMs?: number;\r\n isTest?: boolean;\r\n}\r\n\r\ninterface TriggerRunDetail extends TriggerRunItem {\r\n payload?: unknown;\r\n output?: unknown;\r\n attempts?: {\r\n id: string;\r\n status: string;\r\n error?: { message: string; name?: string; stackTrace?: string };\r\n startedAt?: string;\r\n completedAt?: string;\r\n }[];\r\n}\r\n\r\nconst TERMINAL_STATUSES = new Set([\r\n 'COMPLETED', 'FAILED', 'CRASHED', 'CANCELED',\r\n 'SYSTEM_FAILURE', 'INTERRUPTED', 'EXPIRED',\r\n]);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hardcoded infra constants — single Trigger.dev instance\r\n// ---------------------------------------------------------------------------\r\n\r\n/** SSH server that hosts the Trigger.dev Docker Compose stack. */\r\nconst TRIGGER_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\n\r\n/** Docker Compose project name on the server. */\r\nconst COMPOSE_PROJECT = 'mg-dashboard-supabase-trigger';\r\n\r\nconst PG_CONTAINER = `${COMPOSE_PROJECT}-postgres-1`;\r\nconst WA_CONTAINER = `${COMPOSE_PROJECT}-webapp-1`;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\n/** MCP tool definitions for Trigger.dev (list projects, runs, details, test, replay). */\r\nexport const TRIGGER_TOOLS = [\r\n {\r\n name: 'trigger-list',\r\n description:\r\n 'List all Trigger.dev projects. Returns the project slug and name. ' +\r\n 'Use the slug as the \"project\" parameter in other trigger-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {},\r\n },\r\n },\r\n {\r\n name: 'trigger-runs',\r\n description:\r\n 'List recent task runs for a Trigger.dev project. ' +\r\n 'Returns run ID, task name, status, duration, and timestamps.\\n\\n' +\r\n 'Common shortcuts: `failedOnly: true` returns only FAILED/CRASHED/SYSTEM_FAILURE/INTERRUPTED/TIMED_OUT. ' +\r\n '`sinceMinutes: 60` filters to runs created in the last hour (combines with status/taskIdentifier).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n status: {\r\n type: 'string',\r\n description: 'Comma-separated status filter: QUEUED,EXECUTING,COMPLETED,FAILED,CRASHED,CANCELED,SYSTEM_FAILURE. Ignored when failedOnly is true.',\r\n },\r\n failedOnly: {\r\n type: 'boolean',\r\n description: 'Shortcut: only return FAILED + CRASHED + SYSTEM_FAILURE + INTERRUPTED + TIMED_OUT runs. Overrides `status` when true.',\r\n },\r\n taskIdentifier: { type: 'string', description: 'Filter by task identifier (e.g. \"hello-world\")' },\r\n sinceMinutes: { type: 'number', description: 'Only runs created in the last N minutes (uses Trigger filter[from]). Max 10080 (= 1 week).' },\r\n limit: { type: 'number', description: 'Max runs to return (default 20, max 100)' },\r\n },\r\n required: ['project'],\r\n },\r\n },\r\n {\r\n name: 'trigger-run',\r\n description:\r\n 'Inspect, create, or replay a Trigger.dev run. Pick the mode with `action`:\\n' +\r\n '- \"detail\": fetch full run state — status, payload, output, error stack traces, and logs. Required: runId.\\n' +\r\n '- \"test\": kick off a task run and (by default) wait for it to complete, returning the final detail in one shot. Required: taskId. Optional: payload (JSON string), waitSeconds (default 60, max 300, set 0 to fire-and-forget).\\n' +\r\n '- \"replay\": re-run a previously failed/completed run with the same payload. Required: runId. Optional: waitSeconds (when >0, also waits for the new run to finish and returns its full detail).\\n\\n' +\r\n 'Tip: replace any old `trigger-run-detail` / `trigger-test-task` / `trigger-replay-run` calls with this single tool — output format is identical.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n action: { type: 'string', enum: ['detail', 'test', 'replay'], description: 'Which run operation to perform.' },\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n runId: { type: 'string', description: 'Run ID (e.g. run_xxxxx). Required for action=\"detail\" or action=\"replay\".' },\r\n taskId: { type: 'string', description: 'Task identifier (e.g. \"hello-world\"). Required for action=\"test\".' },\r\n payload: { type: 'string', description: 'JSON payload string passed to the task (action=\"test\" only).' },\r\n waitSeconds: { type: 'number', description: 'Max seconds to wait for completion. Default 60 (action=\"test\") / 0 (action=\"replay\", fire-and-forget). Max 300. Set 0 to skip the wait.' },\r\n },\r\n required: ['action', 'project'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of Trigger.dev MCP tool names for fast membership checks in the main server switch. */\r\nexport const TRIGGER_TOOL_NAMES = new Set(TRIGGER_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each Trigger.dev tool name to the dashboard module key required to use it (`ci_cd`). */\r\nexport const TRIGGER_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'trigger-list': 'ci_cd',\r\n 'trigger-runs': 'ci_cd',\r\n 'trigger-run': 'ci_cd',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerInstance {\r\n port: string;\r\n apiKey: string;\r\n}\r\n\r\n/**\r\n * Discover the webapp port and the production API key for a specific\r\n * Trigger.dev project by querying Docker and the Postgres container.\r\n * The API key is resolved via a JOIN on Project → RuntimeEnvironment.\r\n */\r\nasync function discoverInstance(\r\n projectSlug: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<TriggerInstance> {\r\n const sql = `SELECT re.\\\\\"apiKey\\\\\" FROM \\\\\"RuntimeEnvironment\\\\\" re `\r\n + `JOIN \\\\\"Project\\\\\" p ON re.\\\\\"projectId\\\\\" = p.id `\r\n + `WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;\r\n\r\n const cmd = [\r\n `PORT=$(docker port \"${WA_CONTAINER}\" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,\r\n `KEY=$(docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null | tr -d '[:space:]')`,\r\n 'echo \"$PORT|$KEY\"',\r\n ].join(' && ');\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n const sepIdx = output.indexOf('|');\r\n\r\n const port = sepIdx > 0 ? output.substring(0, sepIdx) : '';\r\n const apiKey = sepIdx > 0 ? output.substring(sepIdx + 1) : '';\r\n\r\n if (!port) {\r\n throw new Error(\r\n `Could not find webapp port for ${WA_CONTAINER}. Is the container running?`,\r\n );\r\n }\r\n if (!apiKey) {\r\n throw new Error(\r\n `Could not get API key for project \"${projectSlug}\". ` +\r\n 'Check if the project slug is correct (use trigger-list).',\r\n );\r\n }\r\n\r\n return { port, apiKey };\r\n}\r\n\r\n/**\r\n * Fetch console/logger output for a run from the TaskEvent table in Postgres.\r\n * Returns formatted log lines sorted by time, filtered to user-relevant levels.\r\n */\r\nasync function fetchRunLogs(\r\n runId: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<string> {\r\n const sql = `SELECT level, message, \\\\\"isError\\\\\", \\\\\"createdAt\\\\\" `\r\n + `FROM \\\\\"TaskEvent\\\\\" `\r\n + `WHERE \\\\\"runId\\\\\" = '${runId}' `\r\n + `AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') `\r\n + `ORDER BY \\\\\"startTime\\\\\" ASC LIMIT 200`;\r\n\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) return '';\r\n\r\n return output.split('\\n').map((line) => {\r\n const parts = line.split('|');\r\n const level = (parts[0] || '').padEnd(5);\r\n const message = parts[1] || '';\r\n const isError = parts[2] === 't';\r\n const ts = parts[3] || '';\r\n const time = ts ? ts.split(' ')[1]?.substring(0, 8) || '' : '';\r\n const prefix = isError ? '!' : ' ';\r\n return `${prefix}${time} [${level}] ${message}`;\r\n }).join('\\n');\r\n}\r\n\r\n/**\r\n * Execute a curl request against the Trigger.dev REST API via SSH.\r\n * Uses -g (globoff) to prevent curl from interpreting brackets in URLs.\r\n */\r\nasync function triggerApi(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n method: string,\r\n path: string,\r\n body?: string,\r\n): Promise<string> {\r\n const parts = ['curl', '-s', '-g', '--max-time', '30'];\r\n if (method !== 'GET') parts.push('-X', method);\r\n parts.push(`\"http://localhost:${instance.port}${path}\"`);\r\n parts.push(`-H \"Authorization: Bearer ${instance.apiKey}\"`);\r\n if (body) {\r\n parts.push('-H \"Content-Type: application/json\"');\r\n parts.push(`-d '${body.replace(/'/g, \"'\\\\''\")}'`);\r\n }\r\n\r\n const result = await sshExec(conn, parts.join(' '), proxy);\r\n if (result.exitCode !== 0 && !result.stdout) {\r\n throw new Error(\r\n `Trigger.dev API call failed (${method} ${path}): ${result.stderr || `exit code ${result.exitCode}`}`,\r\n );\r\n }\r\n return result.stdout;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatters\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction formatRunsTable(runs: TriggerRunItem[]): string {\r\n if (runs.length === 0) return 'No runs found';\r\n\r\n const lines = runs.map((r) => {\r\n const duration = r.durationMs != null ? `${(r.durationMs / 1000).toFixed(1)}s` : '-';\r\n const test = r.isTest ? ' [TEST]' : '';\r\n const created = r.createdAt ? new Date(r.createdAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' }) : '';\r\n return `${r.id} ${r.taskIdentifier.padEnd(35)} ${r.status.padEnd(16)} ${duration.padStart(8)} ${created}${test}`;\r\n });\r\n\r\n return `${'ID'.padEnd(20)} ${'TASK'.padEnd(35)} ${'STATUS'.padEnd(16)} ${'DURATION'.padStart(8)} CREATED\\n` +\r\n '-'.repeat(110) + '\\n' +\r\n lines.join('\\n');\r\n}\r\n\r\nfunction formatRunDetail(run: TriggerRunDetail): string {\r\n const sections: string[] = [];\r\n\r\n sections.push(`=== Run ${run.id} ===`);\r\n sections.push(`Task: ${run.taskIdentifier}`);\r\n sections.push(`Status: ${run.status}`);\r\n sections.push(`Version: ${run.version || '-'}`);\r\n\r\n if (run.startedAt) sections.push(`Started: ${new Date(run.startedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.finishedAt) sections.push(`Finished: ${new Date(run.finishedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.durationMs != null) sections.push(`Duration: ${(run.durationMs / 1000).toFixed(2)}s`);\r\n\r\n if (run.payload !== undefined) {\r\n const payloadStr = typeof run.payload === 'string'\r\n ? run.payload\r\n : JSON.stringify(run.payload, null, 2);\r\n sections.push('', '--- Payload ---', payloadStr);\r\n }\r\n\r\n if (run.output !== undefined) {\r\n const outputStr = typeof run.output === 'string'\r\n ? run.output\r\n : JSON.stringify(run.output, null, 2);\r\n sections.push('', '--- Output ---', outputStr);\r\n }\r\n\r\n if (run.attempts && run.attempts.length > 0) {\r\n for (const attempt of run.attempts) {\r\n if (attempt.error) {\r\n sections.push(\r\n '',\r\n `--- Error (${attempt.id}) ---`,\r\n `${attempt.error.name || 'Error'}: ${attempt.error.message}`,\r\n );\r\n if (attempt.error.stackTrace) {\r\n sections.push('', attempt.error.stackTrace);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Executes a Trigger.dev–related MCP tool over SSH against the shared Docker Compose stack.\r\n *\r\n * @param name - Tool name (e.g. `trigger-list`, `trigger-runs`).\r\n * @param args - Arguments from the MCP `callTool` request.\r\n * @param deps - Injected `sshExec` and `getServerConnection` implementations.\r\n * @returns MCP-formatted result with human-readable text content.\r\n * @throws {Error} When a JSON payload for `trigger-test-task` is invalid, or discovery/API calls fail critically.\r\n */\r\nexport async function handleTriggerTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n deps: TriggerToolDeps,\r\n): Promise<ToolResult> {\r\n const { sshExec, getServerConnection } = deps;\r\n const { conn, proxy } = await getServerConnection(TRIGGER_SERVER_ID);\r\n\r\n switch (name) {\r\n // -----------------------------------------------------------------\r\n case 'trigger-list': {\r\n const sql = 'SELECT slug, name FROM \\\\\"Project\\\\\" ORDER BY name';\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) {\r\n return { content: [{ type: 'text', text: 'No Trigger.dev projects found.' }] };\r\n }\r\n\r\n const header = `${'SLUG'.padEnd(25)} NAME`;\r\n const sep = '-'.repeat(55);\r\n const lines = output.split('\\n').map((line) => {\r\n const [slug, name] = line.split('|');\r\n return `${(slug || '').padEnd(25)} ${name || ''}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-runs': {\r\n const project = String(args.project);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 100);\r\n const queryParts = [`page%5Bsize%5D=${limit}`];\r\n\r\n const failedOnly = args.failedOnly === true;\r\n const statusArg = failedOnly\r\n ? 'FAILED,CRASHED,SYSTEM_FAILURE,INTERRUPTED,TIMED_OUT'\r\n : (args.status ? String(args.status) : '');\r\n if (statusArg) queryParts.push(`filter%5Bstatus%5D=${encodeURIComponent(statusArg)}`);\r\n\r\n if (args.taskIdentifier) {\r\n queryParts.push(`filter%5BtaskIdentifier%5D=${encodeURIComponent(String(args.taskIdentifier))}`);\r\n }\r\n\r\n const sinceMinutes = Number(args.sinceMinutes);\r\n if (Number.isFinite(sinceMinutes) && sinceMinutes > 0) {\r\n const capped = Math.min(sinceMinutes, 10080);\r\n const fromMs = Date.now() - capped * 60_000;\r\n queryParts.push(`filter%5Bfrom%5D=${fromMs}`);\r\n }\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v1/runs?${queryParts.join('&')}`,\r\n );\r\n\r\n let parsed: { data?: TriggerRunItem[] };\r\n try {\r\n parsed = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runs = parsed.data || [];\r\n return { content: [{ type: 'text', text: formatRunsTable(runs) }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-run': {\r\n const action = String(args.action);\r\n if (action !== 'detail' && action !== 'test' && action !== 'replay') {\r\n return { content: [{ type: 'text', text: 'Error: action must be one of: detail, test, replay' }] };\r\n }\r\n const project = String(args.project);\r\n\r\n if (action === 'detail') {\r\n const runId = String(args.runId ?? '');\r\n if (!runId) return { content: [{ type: 'text', text: 'Error: action=\"detail\" requires runId' }] };\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n return await fetchAndFormatRun(conn, proxy, sshExec, instance, runId);\r\n }\r\n\r\n if (action === 'test') {\r\n const taskId = String(args.taskId ?? '');\r\n if (!taskId) return { content: [{ type: 'text', text: 'Error: action=\"test\" requires taskId' }] };\r\n\r\n const waitArg = args.waitSeconds === undefined ? 60 : Number(args.waitSeconds);\r\n const waitSeconds = Math.min(Math.max(Number.isFinite(waitArg) ? waitArg : 60, 0), 300);\r\n conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n let payload = '{}';\r\n if (args.payload) {\r\n try {\r\n JSON.parse(String(args.payload));\r\n payload = String(args.payload);\r\n } catch {\r\n throw new Error(`Invalid JSON payload: ${String(args.payload).substring(0, 200)}`);\r\n }\r\n }\r\n\r\n const triggerBody = JSON.stringify({\r\n payload: JSON.parse(payload),\r\n options: { tags: ['mcp-test'], test: true },\r\n });\r\n\r\n const triggerJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/tasks/${encodeURIComponent(taskId)}/trigger`,\r\n triggerBody,\r\n );\r\n\r\n let triggerResp: { id?: string };\r\n try {\r\n triggerResp = JSON.parse(triggerJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Failed to trigger task. API response:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runId = triggerResp.id;\r\n if (!runId) {\r\n return { content: [{ type: 'text', text: `Trigger API did not return a run ID:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (waitSeconds === 0) {\r\n return { content: [{ type: 'text', text: `Run triggered. ID: ${runId} (fire-and-forget; use action=\"detail\" to check).` }] };\r\n }\r\n\r\n return await waitForCompletion(conn, proxy, sshExec, instance, runId, waitSeconds);\r\n }\r\n\r\n // action === 'replay'\r\n const runId = String(args.runId ?? '');\r\n if (!runId) return { content: [{ type: 'text', text: 'Error: action=\"replay\" requires runId' }] };\r\n\r\n const waitArg = args.waitSeconds === undefined ? 0 : Number(args.waitSeconds);\r\n const waitSeconds = Math.min(Math.max(Number.isFinite(waitArg) ? waitArg : 0, 0), 300);\r\n if (waitSeconds > 0) conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/runs/${encodeURIComponent(runId)}/replay`,\r\n );\r\n\r\n let result: { id?: string };\r\n try {\r\n result = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (!result.id) {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (waitSeconds === 0) {\r\n return { content: [{ type: 'text', text: `Run replayed. New run ID: ${result.id} (use action=\"detail\" to check status).` }] };\r\n }\r\n\r\n return await waitForCompletion(conn, proxy, sshExec, instance, result.id, waitSeconds);\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown trigger tool: ${name}` }] };\r\n }\r\n}\r\n\r\n/** Fetch a run by ID and format it together with its console/logger output. */\r\nasync function fetchAndFormatRun(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n runId: string,\r\n): Promise<ToolResult> {\r\n const [rawJson, logs] = await Promise.all([\r\n triggerApi(conn, proxy, sshExec, instance, 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`),\r\n fetchRunLogs(runId, conn, proxy, sshExec),\r\n ]);\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n let text = formatRunDetail(run);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n}\r\n\r\n/** Poll a run until terminal status or budget expires, then return full detail. */\r\nasync function waitForCompletion(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n runId: string,\r\n waitSeconds: number,\r\n): Promise<ToolResult> {\r\n const pollInterval = 3000;\r\n const maxPolls = Math.ceil((waitSeconds * 1000) / pollInterval);\r\n\r\n for (let i = 0; i < maxPolls; i++) {\r\n await new Promise((r) => setTimeout(r, pollInterval));\r\n\r\n const pollJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`,\r\n );\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(pollJson);\r\n } catch {\r\n continue;\r\n }\r\n\r\n if (TERMINAL_STATUSES.has(run.status)) {\r\n let text = formatRunDetail(run);\r\n const logs = await fetchRunLogs(runId, conn, proxy, sshExec);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Run ${runId} did not complete within ${waitSeconds}s (still running). Use action=\"detail\" with this runId to check later.`,\r\n }],\r\n };\r\n}\r\n","#!/usr/bin/env node\n\nimport {\n createCipheriv,\n createDecipheriv,\n createHash,\n randomBytes,\n} from \"crypto\";\nimport { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { createReadStream, existsSync, statSync } from \"node:fs\";\nimport { mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createServer as createHttpServer } from \"node:http\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { Readable } from \"node:stream\";\nimport { getDb } from \"@mgboiler/db/client\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n isInitializeRequest,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { sql } from \"drizzle-orm\";\nimport { Client as SshClient } from \"ssh2\";\nimport { fetchViaSshProxy } from \"./mijnhost-fetch.js\";\nimport {\n REPO_TOOLS,\n REPO_TOOL_MODULE_MAP,\n REPO_TOOL_NAMES,\n handleRepoTool,\n} from \"./repo-tools.js\";\nimport {\n TRIGGER_TOOLS,\n TRIGGER_TOOL_MODULE_MAP,\n TRIGGER_TOOL_NAMES,\n handleTriggerTool,\n} from \"./trigger-tools.js\";\n\n// ---------------------------------------------------------------------------\n// CLI argument parsing\n// ---------------------------------------------------------------------------\n\nconst args = process.argv.slice(2);\n\nfunction getArg(name: string): string | undefined {\n return args\n .find((a) => a.startsWith(`--${name}=`))\n ?.split(\"=\")\n .slice(1)\n .join(\"=\");\n}\n\n// ---------------------------------------------------------------------------\n// Proxy-bridge mode: when --proxy-url is given we bypass the rest of this\n// file entirely and run as a thin SSH-key-authenticated bridge to a remote\n// MCP HTTP endpoint.\n// ---------------------------------------------------------------------------\nconst proxyUrl = getArg(\"proxy-url\") || process.env.MG_DASHBOARD_PROXY_URL;\nif (proxyUrl) {\n const { runProxyMode } = await import(\"./proxy-mode.js\");\n await runProxyMode(args);\n // runProxyMode never resolves under normal operation; if it does, exit.\n process.exit(0);\n}\n\nconst apiKey = getArg(\"api-key\") || process.env.MG_DASHBOARD_API_KEY;\nconst sshKeyPath = getArg(\"ssh-key\") || process.env.MG_DASHBOARD_SSH_KEY;\nlet databaseUrl =\n getArg(\"database-url\") ||\n process.env.DATABASE_PRIMARY_POOLER_URL ||\n process.env.DATABASE_PRIMARY_URL;\nconst encryptionKey = getArg(\"encryption-key\") || process.env.ENCRYPTION_KEY;\nconst mijnhostApiKey =\n getArg(\"mijnhost-api-key\") || process.env.MIJNHOST_API_KEY;\nfunction isMijnhostViaSshProxyEnabled(): boolean {\n const arg = getArg(\"mijnhost-via-ssh-proxy\");\n if (arg === \"false\" || arg === \"0\") return false;\n const env = process.env.MG_DASHBOARD_MIJNHOST_VIA_SSH_PROXY;\n if (env === \"0\" || env === \"false\") return false;\n return true;\n}\nconst mijnhostViaSshProxy = isMijnhostViaSshProxyEnabled();\nconst dbSshTunnel =\n getArg(\"db-ssh-tunnel\") || process.env.MG_DASHBOARD_DB_SSH_TUNNEL;\nconst dbRemoteEnvFile =\n getArg(\"db-remote-env-file\") || process.env.MG_DASHBOARD_DB_REMOTE_ENV_FILE;\nconst dbRemoteEnvKey =\n getArg(\"db-remote-env-key\") ||\n process.env.MG_DASHBOARD_DB_REMOTE_ENV_KEY ||\n \"DATABASE_PRIMARY_URL\";\nconst httpMode = args.includes(\"--http\");\nconst httpPort = Number(getArg(\"port\")) || 3100;\n\nif (!apiKey || !sshKeyPath) {\n console.error(\n \"Authentication required. Use both --api-key=dk_xxx and --ssh-key=PATH (path to your SSH private or public key), or set MG_DASHBOARD_API_KEY and MG_DASHBOARD_SSH_KEY.\",\n );\n process.exit(1);\n}\n\nif (dbRemoteEnvFile && !dbSshTunnel) {\n console.error(\n \"--db-remote-env-file requires --db-ssh-tunnel (the same SSH connection is used to read the env value).\",\n );\n process.exit(1);\n}\n\nif (dbRemoteEnvFile) {\n const { fetchRemoteEnvValue } = await import(\"./db-ssh-tunnel.js\");\n databaseUrl = await fetchRemoteEnvValue({\n sshTarget: dbSshTunnel!,\n sshKeyPath,\n remoteEnvPath: dbRemoteEnvFile,\n envKey: dbRemoteEnvKey,\n });\n}\n\nif (!databaseUrl) {\n console.error(\n \"Database URL required. Provide one of:\\n --database-url=postgres://...\\n --db-remote-env-file=/path/.env (combined with --db-ssh-tunnel)\\n DATABASE_PRIMARY_URL or DATABASE_PRIMARY_POOLER_URL env var\",\n );\n process.exit(1);\n}\n\nif (dbSshTunnel) {\n const { openDbSshTunnel } = await import(\"./db-ssh-tunnel.js\");\n const tunnel = await openDbSshTunnel({\n sshTarget: dbSshTunnel,\n sshKeyPath,\n databaseUrl,\n });\n databaseUrl = tunnel.rewrittenDatabaseUrl;\n process.on(\"exit\", () => {\n void tunnel.close();\n });\n}\n\nprocess.env.DATABASE_PRIMARY_URL = databaseUrl;\nprocess.env.DATABASE_PRIMARY_POOLER_URL = databaseUrl;\n\nconst db = getDb();\n\nif (mijnhostApiKey && mijnhostViaSshProxy) {\n console.error(\"[mcp][mijnhost] Routing mijn.host API via SSH proxy\");\n}\n\n// ---------------------------------------------------------------------------\n// Rate limiting\n// ---------------------------------------------------------------------------\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nclass RateLimiter {\n private buckets = new Map<string, RateLimitEntry>();\n private readonly maxAttempts: number;\n private readonly windowMs: number;\n\n constructor(maxAttempts: number, windowMs: number) {\n this.maxAttempts = maxAttempts;\n this.windowMs = windowMs;\n }\n\n /**\n * Check if an action is allowed for the given key.\n * Increments the counter and returns whether the action should proceed.\n */\n check(key: string): {\n allowed: boolean;\n remaining: number;\n retryAfterMs: number;\n } {\n const now = Date.now();\n const entry = this.buckets.get(key);\n\n if (!entry || now >= entry.resetAt) {\n this.buckets.set(key, { count: 1, resetAt: now + this.windowMs });\n return {\n allowed: true,\n remaining: this.maxAttempts - 1,\n retryAfterMs: 0,\n };\n }\n\n entry.count++;\n\n if (entry.count > this.maxAttempts) {\n return {\n allowed: false,\n remaining: 0,\n retryAfterMs: entry.resetAt - now,\n };\n }\n\n return {\n allowed: true,\n remaining: this.maxAttempts - entry.count,\n retryAfterMs: 0,\n };\n }\n\n /** Periodically remove expired entries to prevent unbounded growth. */\n cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.buckets) {\n if (now >= entry.resetAt) this.buckets.delete(key);\n }\n }\n}\n\nconst authRateLimiter = new RateLimiter(5, 15 * 60 * 1000);\n\n// Cleanup expired rate limit entries every 5 minutes\nsetInterval(\n () => {\n authRateLimiter.cleanup();\n },\n 5 * 60 * 1000,\n).unref();\n\n// Tool-level rate limiting was previously gated per category (ssh / sftp / db\n// / default) with hourly buckets. Removed because legitimate dev sessions\n// regularly burst over those caps and the resulting \"MCP Rate Limit\" stalls\n// were strictly noise — auth-level rate limiting (failed login attempts)\n// remains in place above for the actual security concern.\n\n// ---------------------------------------------------------------------------\n// Audit logging\n// ---------------------------------------------------------------------------\n\nconst SENSITIVE_KEYS = new Set([\n \"password\",\n \"private_key\",\n \"passphrase\",\n \"secret\",\n \"token\",\n \"key\",\n \"api_key\",\n \"credentials\",\n]);\n\nfunction redactSensitiveArgs(\n args: Record<string, unknown>,\n): Record<string, unknown> {\n const redacted: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(args)) {\n if (SENSITIVE_KEYS.has(k.toLowerCase())) {\n redacted[k] = \"[REDACTED]\";\n } else if (typeof v === \"string\" && v.length > 500) {\n redacted[k] = v.slice(0, 500) + \"...[truncated]\";\n } else {\n redacted[k] = v;\n }\n }\n return redacted;\n}\n\nasync function writeAuditLog(entry: {\n toolName: string;\n arguments?: Record<string, unknown>;\n ipAddress?: string;\n serverId?: string;\n resultStatus: \"success\" | \"error\";\n errorMessage?: string;\n durationMs?: number;\n}): Promise<void> {\n if (!authContext) return;\n try {\n const argsJson = entry.arguments\n ? JSON.stringify(redactSensitiveArgs(entry.arguments))\n : null;\n await db.execute(sql`\n INSERT INTO mcp_audit_log (\n api_key_id, user_id, tool_name, arguments, ip_address,\n server_id, result_status, error_message, duration_ms\n ) VALUES (\n ${authContext.apiKeyId},\n ${authContext.userId},\n ${entry.toolName},\n ${argsJson}::jsonb,\n ${entry.ipAddress || null},\n ${entry.serverId || null},\n ${entry.resultStatus},\n ${entry.errorMessage?.slice(0, 1000) || null},\n ${entry.durationMs || null}\n )\n `);\n } catch (err) {\n console.error(\n \"[Audit] Failed to write audit log:\",\n err instanceof Error ? err.message : err,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Permission model (mirrors packages/boiler/src/utils/permissions.ts)\n// ---------------------------------------------------------------------------\n\nconst MODULE_KEYS = [\n \"users\",\n \"ssh_servers\",\n \"wiki\",\n \"ci_cd\",\n \"domains\",\n \"settings\",\n \"repositories\",\n] as const;\n\ntype ModuleKey = (typeof MODULE_KEYS)[number];\n\ninterface ModulePermissions {\n users?: boolean;\n ssh_servers?: boolean;\n wiki?: boolean;\n ci_cd?: boolean;\n\n domains?: boolean;\n settings?: boolean;\n repositories?: boolean;\n}\n\ninterface ResourcePermissions {\n ssh_servers: string[];\n}\n\ninterface UserPermissions {\n modules: ModulePermissions;\n resources: ResourcePermissions;\n}\n\nconst FULL_PERMISSIONS: UserPermissions = {\n modules: Object.fromEntries(\n MODULE_KEYS.map((k) => [k, true]),\n ) as ModulePermissions,\n resources: { ssh_servers: [\"*\"] },\n};\n\nfunction parsePermissions(raw: unknown): Partial<UserPermissions> | null {\n if (!raw || typeof raw !== \"object\") return null;\n return raw as Partial<UserPermissions>;\n}\n\nfunction resolvePermissions(\n roleName: string,\n roleDefaults: unknown,\n userOverrides: unknown,\n): UserPermissions {\n if (roleName === \"superadmin\") return FULL_PERMISSIONS;\n\n const base = parsePermissions(roleDefaults);\n const overrides = parsePermissions(userOverrides);\n\n const modules: ModulePermissions = {} as ModulePermissions;\n for (const key of MODULE_KEYS) {\n const userVal = overrides?.modules?.[key];\n const roleVal = base?.modules?.[key];\n (modules as Record<string, boolean>)[key] =\n userVal !== undefined ? userVal : roleVal !== undefined ? roleVal : false;\n }\n\n const resources: ResourcePermissions = {\n ssh_servers:\n overrides?.resources?.ssh_servers ?? base?.resources?.ssh_servers ?? [],\n };\n\n return { modules, resources };\n}\n\n/**\n * Intersect key-level server restrictions with user permission resources.\n * Most restrictive wins: if both specify lists, return the overlap.\n */\nfunction intersectServerAccess(\n keyServerIds: string[] | null,\n permissionServerIds: string[],\n): string[] | null {\n const keyHasRestriction = keyServerIds !== null;\n const permWildcard = permissionServerIds.includes(\"*\");\n const permEmpty = permissionServerIds.length === 0;\n\n if (!keyHasRestriction && permWildcard) return null; // unrestricted\n if (!keyHasRestriction && permEmpty) return [];\n if (!keyHasRestriction) return permissionServerIds;\n if (permWildcard) return keyServerIds;\n if (permEmpty) return [];\n return keyServerIds.filter((id) => permissionServerIds.includes(id));\n}\n\n/** Maps each MCP tool to the module permission it requires. */\nconst TOOL_MODULE_MAP: Partial<Record<string, ModuleKey>> = {\n \"list-servers\": \"ssh_servers\",\n \"ssh-execute\": \"ssh_servers\",\n \"sftp-list\": \"ssh_servers\",\n \"sftp-read\": \"ssh_servers\",\n \"sftp-write\": \"ssh_servers\",\n \"sftp-delete\": \"ssh_servers\",\n \"docker-list\": \"ssh_servers\",\n \"docker-logs\": \"ssh_servers\",\n \"docker-exec\": \"ssh_servers\",\n \"docker-compose\": \"ssh_servers\",\n \"wait-for\": \"ssh_servers\",\n \"db-discover\": \"ssh_servers\",\n \"db-tables\": \"ssh_servers\",\n \"db-query\": \"ssh_servers\",\n \"db-apply-migration\": \"ssh_servers\",\n \"db-list-migrations\": \"ssh_servers\",\n \"cache-purge\": \"ssh_servers\",\n \"env-list\": \"ci_cd\",\n \"env-get\": \"ci_cd\",\n \"env-store\": \"ci_cd\",\n \"domain-list\": \"domains\",\n \"dns-list\": \"domains\",\n \"dns-record\": \"domains\",\n ...TRIGGER_TOOL_MODULE_MAP,\n ...REPO_TOOL_MODULE_MAP,\n};\n\n// ---------------------------------------------------------------------------\n// Auth context\n// ---------------------------------------------------------------------------\n\ninterface AuthContext {\n apiKeyId: string;\n apiKeyName: string;\n userId: string;\n allowedServerIds: string[] | null;\n permissions: UserPermissions;\n roleName: string;\n}\n\n// ---------------------------------------------------------------------------\n// Database row shapes (Drizzle raw SQL results)\n// ---------------------------------------------------------------------------\n\ninterface ApiKeyRow extends Record<string, unknown> {\n id: string;\n name: string | null;\n created_by: string;\n allowed_server_ids: string[] | null;\n is_active: boolean;\n expires_at: string | null;\n}\n\ninterface UserWithRoleRow extends Record<string, unknown> {\n permissions: unknown;\n role_name: string | null;\n role_default_permissions: unknown;\n}\n\ninterface SshKeyRow extends Record<string, unknown> {\n id: string;\n name: string | null;\n api_key_id: string;\n is_active: boolean;\n}\n\ninterface SshServerCredentialRow extends Record<string, unknown> {\n hostname: string;\n port: number | null;\n username: string;\n password_encrypted: string | null;\n ssh_key_encrypted: string | null;\n ssh_key_passphrase_encrypted: string | null;\n os_type?: string | null;\n}\n\ninterface SshServerNameRow extends Record<string, unknown> {\n id?: string;\n name: string | null;\n}\n\ninterface SshServerListRow extends Record<string, unknown> {\n id: string;\n name: string;\n hostname: string;\n port: number | null;\n username: string;\n tags: string[] | null;\n hosted_by: string | null;\n os_type: string | null;\n created_at: string;\n}\n\ninterface ReleaseProfileRow extends Record<string, unknown> {\n id: string;\n name: string;\n}\n\ninterface ReleaseProfileStageIdRow extends Record<string, unknown> {\n id: string;\n}\n\ninterface ReleaseProfileStageWithProfileRow extends Record<string, unknown> {\n id: string;\n release_profile_id: string;\n}\n\ninterface EnvConfigListRow extends Record<string, unknown> {\n id: string;\n app_name: string;\n environment: string;\n description: string | null;\n updated_at: string;\n release_profile_stage_id: string | null;\n}\n\ninterface EnvConfigEncryptedRow extends Record<string, unknown> {\n env_data_encrypted: string;\n release_profile_stage_id: string | null;\n}\n\nlet authContext: AuthContext | null = null;\n\nasync function validateApiKey(key: string): Promise<AuthContext | null> {\n if (!key.startsWith(\"dk_\") || key.length !== 67) {\n console.error(\"Invalid API key format (expected dk_ + 64 hex chars)\");\n return null;\n }\n\n const keyHash = createHash(\"sha256\").update(key).digest(\"hex\");\n\n const rateCheck = authRateLimiter.check(keyHash);\n if (!rateCheck.allowed) {\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\n console.error(\n `Rate limited: too many failed auth attempts. Retry in ${retryMin} minute(s).`,\n );\n return null;\n }\n\n const apiKeyRows = await db.execute<ApiKeyRow>(sql`\n SELECT id, name, created_by, allowed_server_ids, is_active, expires_at\n FROM dashboard_mcp_api_key\n WHERE api_key_hash = ${keyHash} AND is_active = true\n LIMIT 1\n `);\n const data = apiKeyRows[0];\n\n if (!data) {\n console.error(\n `API key not found or inactive (${rateCheck.remaining} attempts remaining)`,\n );\n return null;\n }\n\n if (data.expires_at && new Date(data.expires_at) < new Date()) {\n console.error(\n `API key has expired (${rateCheck.remaining} attempts remaining)`,\n );\n return null;\n }\n\n const userRows = await db.execute<UserWithRoleRow>(sql`\n SELECT u.permissions, r.name AS role_name, r.default_permissions AS role_default_permissions\n FROM \"user\" u\n LEFT JOIN role r ON r.id = u.role_id\n WHERE u.id = ${data.created_by}\n LIMIT 1\n `);\n const userData = userRows[0];\n\n if (!userData) {\n console.error(`User not found for API key creator: ${data.created_by}`);\n return null;\n }\n\n const roleName = userData.role_name || \"user\";\n const roleDefaults = userData.role_default_permissions ?? {};\n const userOverrides = userData.permissions ?? null;\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\n\n const allowedServerIds = intersectServerAccess(\n data.allowed_server_ids,\n permissions.resources.ssh_servers,\n );\n\n await db.execute(sql`\n UPDATE dashboard_mcp_api_key\n SET last_used_at = ${new Date().toISOString()}\n WHERE id = ${data.id}\n `);\n\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\n console.error(\n `Authenticated as user ${data.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`,\n );\n\n return {\n apiKeyId: data.id,\n apiKeyName: data.name || \"Unknown\",\n userId: data.created_by,\n allowedServerIds,\n permissions,\n roleName,\n };\n}\n\n// ---------------------------------------------------------------------------\n// SSH-key authentication\n// ---------------------------------------------------------------------------\n\n/** Run a child process and return { stdout, stderr, code }. Never throws. */\nfunction runProcess(\n command: string,\n argv: string[],\n options: { stdin?: string; cwd?: string } = {},\n): Promise<{ stdout: string; stderr: string; code: number }> {\n return new Promise((resolve) => {\n const child = spawn(command, argv, {\n cwd: options.cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n child.on(\"error\", (err) => {\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\n });\n child.on(\"close\", (code) => {\n resolve({ stdout, stderr, code: code ?? -1 });\n });\n if (options.stdin !== undefined) {\n child.stdin.write(options.stdin);\n child.stdin.end();\n } else {\n child.stdin.end();\n }\n });\n}\n\n/**\n * Resolve the user's SSH public-key file from the path they passed.\n *\n * Accepts either a `.pub` file directly, or a private-key path (in which case\n * we look for `${path}.pub` next to it). Returns the public-key file path and\n * its contents trimmed.\n */\nasync function resolvePubkeyFile(\n input: string,\n): Promise<{ pubPath: string; pubText: string }> {\n const expand = (p: string) =>\n p.startsWith(\"~\")\n ? join(process.env.HOME || process.env.USERPROFILE || \"\", p.slice(1))\n : p;\n const candidate = expand(input);\n let pubPath: string;\n if (candidate.endsWith(\".pub\")) {\n pubPath = candidate;\n } else if (existsSync(`${candidate}.pub`)) {\n pubPath = `${candidate}.pub`;\n } else if (existsSync(candidate)) {\n // Caller passed a public-key file without `.pub` extension; tolerate it.\n pubPath = candidate;\n } else {\n throw new Error(\n `SSH key file not found: ${candidate} (also tried ${candidate}.pub)`,\n );\n }\n const pubText = (await readFile(pubPath, \"utf8\")).trim();\n if (!pubText) {\n throw new Error(`SSH public-key file is empty: ${pubPath}`);\n }\n return { pubPath, pubText };\n}\n\n/**\n * Compute the OpenSSH SHA256 fingerprint (\"SHA256:abc...\") of a public-key\n * line. This matches the format that `ssh-keygen -lf <pubkey>` prints and\n * what we store in `dashboard_mcp_ssh_key.fingerprint_sha256`.\n */\nfunction computeOpenSshFingerprint(pubkeyLine: string): string {\n const parts = pubkeyLine.trim().split(/\\s+/);\n if (parts.length < 2 || !parts[1]) {\n throw new Error(\n 'Invalid SSH public-key line (expected \"<type> <base64> [comment]\")',\n );\n }\n const bodyBytes = Buffer.from(parts[1], \"base64\");\n const hash = createHash(\"sha256\")\n .update(bodyBytes)\n .digest(\"base64\")\n .replace(/=+$/, \"\");\n return `SHA256:${hash}`;\n}\n\n/**\n * Sign a challenge with the user's SSH key (via ssh-agent or on-disk key).\n * Uses `ssh-keygen -Y sign` (SSHSIG format, OpenSSH >= 8.2).\n *\n * Returns the armored signature (\"-----BEGIN SSH SIGNATURE----- ...\").\n */\nasync function sshKeygenSign(\n pubkeyPath: string,\n challenge: string,\n namespace: string,\n): Promise<string> {\n const result = await runProcess(\n \"ssh-keygen\",\n [\"-Y\", \"sign\", \"-f\", pubkeyPath, \"-n\", namespace, \"-q\"],\n { stdin: challenge },\n );\n if (result.code !== 0) {\n throw new Error(\n `ssh-keygen sign failed (exit ${result.code}). ` +\n `Make sure ssh-agent is running and has the matching private key loaded ` +\n `(or that the private key is at the path next to the .pub file). ` +\n `stderr: ${result.stderr.trim() || \"(empty)\"}`,\n );\n }\n if (!result.stdout.includes(\"BEGIN SSH SIGNATURE\")) {\n throw new Error(\n `ssh-keygen sign produced no signature (stderr: ${result.stderr.trim() || \"(empty)\"})`,\n );\n }\n return result.stdout;\n}\n\n/**\n * Verify an SSHSIG armored signature against a known public-key line.\n * Returns true if the signature is valid.\n */\nasync function sshKeygenVerify(\n pubkeyLine: string,\n signature: string,\n challenge: string,\n namespace: string,\n): Promise<boolean> {\n const dir = await mkdtemp(join(tmpdir(), \"mcp-ssh-verify-\"));\n try {\n const allowedSigners = `mcp@local ${pubkeyLine.trim()}\\n`;\n const allowedPath = join(dir, \"allowed_signers\");\n const sigPath = join(dir, \"sig\");\n await writeFile(allowedPath, allowedSigners, \"utf8\");\n await writeFile(sigPath, signature, \"utf8\");\n const result = await runProcess(\n \"ssh-keygen\",\n [\n \"-Y\",\n \"verify\",\n \"-f\",\n allowedPath,\n \"-I\",\n \"mcp@local\",\n \"-n\",\n namespace,\n \"-s\",\n sigPath,\n \"-q\",\n ],\n { stdin: challenge },\n );\n return result.code === 0;\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => undefined);\n }\n}\n\n/**\n * Authenticate to the dashboard using an SSH key.\n *\n * 1. Read the user's pubkey file and compute its SHA256 fingerprint.\n * 2. Generate a fresh nonce, sign it via `ssh-keygen -Y sign` (uses ssh-agent\n * or the private key on disk), then locally verify the signature against\n * the pubkey we read. This proves the caller actually possesses the\n * private key (or has it loaded in ssh-agent), not just a stolen pubkey.\n * 3. Look up the fingerprint in `dashboard_mcp_ssh_key`, require it to be\n * linked to the already validated API key, then load permissions exactly\n * like the bearer-token path does.\n *\n * The signature step is optional but defaults to ON. Set\n * `MG_DASHBOARD_SSH_SKIP_VERIFY=1` to skip it (e.g. for first-time enrollment\n * before the key is registered, where you just want to print the fingerprint).\n */\nasync function validateSshKey(\n pubkeyPathInput: string,\n expectedApiKeyId: string,\n): Promise<AuthContext | null> {\n let pubPath: string;\n let pubText: string;\n try {\n const resolved = await resolvePubkeyFile(pubkeyPathInput);\n pubPath = resolved.pubPath;\n pubText = resolved.pubText;\n } catch (err) {\n console.error(\n `SSH key error: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n\n let fingerprint: string;\n try {\n fingerprint = computeOpenSshFingerprint(pubText);\n } catch (err) {\n console.error(\n `SSH key error: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n\n const rateCheck = authRateLimiter.check(fingerprint);\n if (!rateCheck.allowed) {\n const retryMin = Math.ceil(rateCheck.retryAfterMs / 60_000);\n console.error(\n `Rate limited: too many failed SSH-key auth attempts. Retry in ${retryMin} minute(s).`,\n );\n return null;\n }\n\n const skipVerify = process.env.MG_DASHBOARD_SSH_SKIP_VERIFY === \"1\";\n if (!skipVerify) {\n try {\n const challenge = randomBytes(32).toString(\"hex\");\n const signature = await sshKeygenSign(\n pubPath,\n challenge,\n \"mg-dashboard-mcp\",\n );\n const verified = await sshKeygenVerify(\n pubText,\n signature,\n challenge,\n \"mg-dashboard-mcp\",\n );\n if (!verified) {\n console.error(\n \"SSH-key challenge verification failed (signature did not validate against the public key).\",\n );\n return null;\n }\n } catch (err) {\n console.error(\n `SSH-key challenge failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n console.error(\n \"Tip: set MG_DASHBOARD_SSH_SKIP_VERIFY=1 to skip the challenge if you only need to print the fingerprint for enrollment.\",\n );\n return null;\n }\n }\n\n const keyRows = await db.execute<SshKeyRow>(sql`\n SELECT id, name, api_key_id, is_active\n FROM dashboard_mcp_ssh_key\n WHERE fingerprint_sha256 = ${fingerprint} AND is_active = true\n LIMIT 1\n `);\n const keyRow = keyRows[0];\n\n if (!keyRow) {\n console.error(\n `SSH key not registered (fingerprint ${fingerprint}; ${rateCheck.remaining} attempts remaining). ` +\n `Add it under MCP API Keys → SSH Keys in the dashboard.`,\n );\n return null;\n }\n\n if (keyRow.api_key_id !== expectedApiKeyId) {\n console.error(\n `SSH key \"${keyRow.name}\" is registered, but it is not linked to the provided MCP API key. ` +\n `Add this SSH key under the same MCP API Key entry used by --api-key.`,\n );\n return null;\n }\n\n const apiRows = await db.execute<ApiKeyRow>(sql`\n SELECT id, name, created_by, allowed_server_ids, is_active, expires_at\n FROM dashboard_mcp_api_key\n WHERE id = ${keyRow.api_key_id} AND is_active = true\n LIMIT 1\n `);\n const apiRow = apiRows[0];\n\n if (!apiRow) {\n console.error(\n \"SSH key is linked to an inactive or missing MCP API key entry.\",\n );\n return null;\n }\n\n if (apiRow.expires_at && new Date(apiRow.expires_at) < new Date()) {\n console.error(\"Linked MCP API key entry has expired.\");\n return null;\n }\n\n const userRows = await db.execute<UserWithRoleRow>(sql`\n SELECT u.permissions, r.name AS role_name, r.default_permissions AS role_default_permissions\n FROM \"user\" u\n LEFT JOIN role r ON r.id = u.role_id\n WHERE u.id = ${apiRow.created_by}\n LIMIT 1\n `);\n const userData = userRows[0];\n\n if (!userData) {\n console.error(`User not found for SSH key creator: ${apiRow.created_by}`);\n return null;\n }\n\n const roleName = userData.role_name || \"user\";\n const roleDefaults = userData.role_default_permissions ?? {};\n const userOverrides = userData.permissions ?? null;\n const permissions = resolvePermissions(roleName, roleDefaults, userOverrides);\n\n const allowedServerIds = intersectServerAccess(\n apiRow.allowed_server_ids,\n permissions.resources.ssh_servers,\n );\n\n const nowIso = new Date().toISOString();\n await Promise.all([\n db.execute(\n sql`UPDATE dashboard_mcp_ssh_key SET last_used_at = ${nowIso} WHERE id = ${keyRow.id}`,\n ),\n db.execute(\n sql`UPDATE dashboard_mcp_api_key SET last_used_at = ${nowIso} WHERE id = ${apiRow.id}`,\n ),\n ]);\n\n const moduleCount = MODULE_KEYS.filter((k) => permissions.modules[k]).length;\n console.error(\n `Authenticated via SSH key \"${keyRow.name}\" (fp ${fingerprint.slice(0, 24)}...) ` +\n `as user ${apiRow.created_by} (role: ${roleName}, modules: ${moduleCount}/${MODULE_KEYS.length})`,\n );\n\n return {\n apiKeyId: apiRow.id,\n apiKeyName: `${apiRow.name || \"Unknown\"} (ssh: ${keyRow.name})`,\n userId: apiRow.created_by,\n allowedServerIds,\n permissions,\n roleName,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Server access helper\n// ---------------------------------------------------------------------------\n\nfunction assertServerAccess(serverId: string): void {\n if (!authContext) throw new Error(\"Not authenticated\");\n if (authContext.allowedServerIds === null) return;\n if (!authContext.allowedServerIds.includes(serverId)) {\n throw new Error(\n `Access denied: you do not have permission for server ${serverId}`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// SQL helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Bind a JS string array as a Postgres `uuid[]` parameter.\n *\n * Drizzle's template-string `sql` tag expands a JS array passed as\n * `${arr}` into a row expression `($1, $2, ...)`. Appending `::uuid[]`\n * then attempts to cast a *row* to an array type, which Postgres rejects\n * with \"cannot cast type record to uuid[]\". This helper instead emits\n * `ARRAY[$1::uuid, $2::uuid, ...]` — each element is still a properly\n * bound parameter, but the surrounding `ARRAY[…]` constructor produces\n * a real `uuid[]` value the planner accepts.\n */\nfunction uuidArrayParam(values: readonly string[]) {\n if (values.length === 0) return sql`ARRAY[]::uuid[]`;\n return sql`ARRAY[${sql.join(\n values.map((v) => sql`${v}::uuid`),\n sql`, `,\n )}]`;\n}\n\n// ---------------------------------------------------------------------------\n// Release profile resolution helper\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a release profile name to its stage IDs.\n * Returns { stageIds, profileId } or throws with available profile names.\n */\nasync function resolveReleaseProfileStageIds(\n profileName: string,\n): Promise<{ stageIds: string[]; profileId: string }> {\n const profileRows = await db.execute<ReleaseProfileRow>(sql`\n SELECT id, name FROM release_profile\n WHERE name ILIKE ${profileName}\n LIMIT 1\n `);\n const profile = profileRows[0];\n\n if (!profile) {\n const all = await db.execute<{ name: string }>(\n sql`SELECT name FROM release_profile ORDER BY name`,\n );\n const names = all.map((p) => p.name).join(\", \");\n throw new Error(\n `Release profile \"${profileName}\" not found. Available profiles: ${names || \"(none)\"}`,\n );\n }\n\n const stages = await db.execute<ReleaseProfileStageIdRow>(sql`\n SELECT id FROM release_profile_stage\n WHERE release_profile_id = ${profile.id}\n `);\n\n if (stages.length === 0) {\n throw new Error(\n `Release profile \"${profile.name}\" has no stages configured`,\n );\n }\n\n return { stageIds: stages.map((s) => s.id), profileId: profile.id };\n}\n\n/**\n * Look up release profile names for a set of stage IDs.\n * Returns a map of stageId -> profileName.\n */\nasync function getProfileNamesForStageIds(\n stageIds: string[],\n): Promise<Record<string, string>> {\n if (stageIds.length === 0) return {};\n\n const stages = await db.execute<ReleaseProfileStageWithProfileRow>(sql`\n SELECT id, release_profile_id FROM release_profile_stage\n WHERE id = ANY(${uuidArrayParam(stageIds)})\n `);\n\n if (stages.length === 0) return {};\n\n const profileIds = [...new Set(stages.map((s) => s.release_profile_id))];\n const profiles = await db.execute<ReleaseProfileRow>(sql`\n SELECT id, name FROM release_profile\n WHERE id = ANY(${uuidArrayParam(profileIds)})\n `);\n\n const profileMap: Record<string, string> = {};\n for (const p of profiles) profileMap[p.id] = p.name;\n\n const result: Record<string, string> = {};\n for (const s of stages) {\n result[s.id] = profileMap[s.release_profile_id] || \"unknown\";\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Encryption helpers (AES-256-GCM, compatible with dashboard encryption.ts)\n// ---------------------------------------------------------------------------\n\nconst ENC_ALGORITHM = \"aes-256-gcm\";\nconst ENC_IV_LENGTH = 16;\nconst ENC_TAG_LENGTH = 16;\n\nfunction getEncryptionKey(): Buffer {\n if (!encryptionKey)\n throw new Error(\"ENCRYPTION_KEY is required for env operations\");\n const buf = Buffer.from(encryptionKey, \"hex\");\n if (buf.length !== 32)\n throw new Error(\"ENCRYPTION_KEY must be a 64-character hex string\");\n return buf;\n}\n\nfunction encrypt(text: string): string {\n const key = getEncryptionKey();\n const iv = randomBytes(ENC_IV_LENGTH);\n const cipher = createCipheriv(\n ENC_ALGORITHM,\n new Uint8Array(key),\n new Uint8Array(iv),\n );\n let encrypted = cipher.update(text, \"utf8\", \"hex\");\n encrypted += cipher.final(\"hex\");\n const authTag = cipher.getAuthTag();\n return Buffer.concat([\n new Uint8Array(iv),\n new Uint8Array(authTag),\n new Uint8Array(Buffer.from(encrypted, \"hex\")),\n ]).toString(\"base64\");\n}\n\nfunction decrypt(payload: string): string {\n const key = getEncryptionKey();\n const buf = Buffer.from(payload, \"base64\");\n const iv = buf.subarray(0, ENC_IV_LENGTH);\n const authTag = buf.subarray(ENC_IV_LENGTH, ENC_IV_LENGTH + ENC_TAG_LENGTH);\n const encrypted = buf.subarray(ENC_IV_LENGTH + ENC_TAG_LENGTH);\n const decipher = createDecipheriv(\n ENC_ALGORITHM,\n new Uint8Array(key),\n new Uint8Array(iv),\n );\n decipher.setAuthTag(new Uint8Array(authTag));\n let decrypted = decipher.update(encrypted.toString(\"hex\"), \"hex\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n}\n\n// ---------------------------------------------------------------------------\n// SSH helpers\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Shell quoting / OS-aware command builders\n// ---------------------------------------------------------------------------\n\n/**\n * POSIX shell single-quote escape. Wraps in `'...'` and escapes any embedded\n * `'` as `'\\''`. Bare-word fast-path for safe characters skips quoting.\n * Used by ssh-execute (linux mode), docker-exec, sftp-list pattern building,\n * and anywhere we previously relied on the LLM to escape `$`, `#`, spaces,\n * etc. inside command strings.\n */\nfunction posixQuote(arg: string): string {\n if (arg === \"\") return \"''\";\n if (/^[A-Za-z0-9._\\/=:@%+\\-]+$/.test(arg)) return arg;\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n\n/**\n * Build a POSIX shell command line from a program + argv. The program itself\n * is NOT quoted if it's a simple identifier/path (so `cd` / `docker compose`\n * keep working when passed as `command: 'docker compose'` with args).\n */\nfunction buildPosixCommand(command: string, args: string[]): string {\n const program = /^[A-Za-z0-9._\\/\\- ]+$/.test(command)\n ? command\n : posixQuote(command);\n if (args.length === 0) return program;\n return `${program} ${args.map(posixQuote).join(\" \")}`;\n}\n\n/**\n * Build a PowerShell `-EncodedCommand` invocation. PowerShell decodes the\n * UTF-16LE-base64 payload itself, so embedded `$`, `'`, `\"`, `#`, spaces, etc.\n * never see cmd.exe parsing — this is the only quoting-safe way to call\n * PowerShell over SSH on Windows servers.\n */\nfunction buildPowerShellEncodedCommand(\n command: string,\n args: string[],\n): string {\n const psSingleQuote = (s: string) => \"'\" + s.replace(/'/g, \"''\") + \"'\";\n let body: string;\n if (args.length === 0) {\n body = command;\n } else {\n body = `& ${psSingleQuote(command)} ${args.map(psSingleQuote).join(\" \")}`;\n }\n // Suppress PowerShell's progress CLIXML stream that otherwise pollutes stderr\n // with `<Objs Version=\"1.1.0.1\" ...>` blobs on first use of certain cmdlets.\n const psExpr = `$ProgressPreference='SilentlyContinue'; ${body}`;\n const utf16 = Buffer.from(psExpr, \"utf16le\");\n const b64 = utf16.toString(\"base64\");\n // -OutputFormat Text disables PowerShell's CLIXML serialization of errors/objects\n // when run as a subprocess (default is XML for non-interactive). Combined with\n // $ProgressPreference above, this gives clean text on stdout/stderr.\n return `powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand ${b64}`;\n}\n\ninterface SshConnectionOptions {\n hostname: string;\n port: number;\n username: string;\n password?: string;\n privateKey?: string;\n passphrase?: string;\n timeout?: number;\n}\n\ninterface SshResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nconst SSH_PROXY_SERVER_ID = \"03659d55-e194-400d-b82a-bf6457371ded\";\nlet _proxyConnCache: SshConnectionOptions | null = null;\n\nasync function getProxyConnection(): Promise<SshConnectionOptions> {\n if (_proxyConnCache) return _proxyConnCache;\n\n const rows = await db.execute<SshServerCredentialRow>(sql`\n SELECT\n ms.hostname,\n ms.port,\n ms.username,\n sc.password_encrypted,\n sc.ssh_key_encrypted,\n sc.ssh_key_passphrase_encrypted\n FROM managed_server ms\n LEFT JOIN server_credential sc ON sc.server_id = ms.id\n WHERE ms.id = ${SSH_PROXY_SERVER_ID}\n LIMIT 1\n `);\n const data = rows[0];\n\n if (!data) throw new Error(\"SSH Proxy server not found in database\");\n if (!encryptionKey)\n throw new Error(\"ENCRYPTION_KEY required to decrypt server credentials\");\n if (!data.password_encrypted && !data.ssh_key_encrypted) {\n throw new Error(\"SSH Proxy server has no credentials in server_credential\");\n }\n\n _proxyConnCache = {\n hostname: data.hostname,\n port: data.port || 22,\n username: data.username,\n password: data.password_encrypted\n ? decrypt(data.password_encrypted)\n : undefined,\n privateKey: data.ssh_key_encrypted\n ? decrypt(data.ssh_key_encrypted)\n : undefined,\n passphrase: data.ssh_key_passphrase_encrypted\n ? decrypt(data.ssh_key_passphrase_encrypted)\n : undefined,\n };\n return _proxyConnCache;\n}\n\ntype ServerOs = \"linux\" | \"windows\";\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Resolve a `serverId` argument to a real UUID. Accepts:\n * - a UUID (returned as-is, fast path)\n * - an exact server name (case-sensitive equality)\n * - a fuzzy partial name (case-insensitive `ILIKE %x%`)\n *\n * Falls back to a clear error listing close matches when ambiguous. Saves a\n * `list-servers` roundtrip per session — the LLM can pass \"MG Giga Server\"\n * straight into `ssh-execute serverId=\"MG Giga Server\"` instead of having\n * to first look up the UUID.\n */\nasync function resolveServerId(input: string): Promise<string> {\n const trimmed = (input ?? \"\").trim();\n if (!trimmed) throw new Error(\"serverId is required\");\n if (UUID_RE.test(trimmed)) return trimmed;\n\n const exact = await db.execute<{ id: string; name: string }>(sql`\n SELECT id, name FROM managed_server WHERE name = ${trimmed} LIMIT 2\n `);\n if (exact.length === 1) {\n KNOWN_SERVER_NAMES.set(exact[0]!.id, {\n id: exact[0]!.id,\n name: exact[0]!.name,\n });\n return exact[0]!.id;\n }\n if (exact.length > 1) {\n throw new Error(\n `Multiple servers share the exact name \"${trimmed}\". Pass the UUID instead.`,\n );\n }\n\n const fuzzy = await db.execute<{ id: string; name: string }>(sql`\n SELECT id, name\n FROM managed_server\n WHERE name ILIKE ${\"%\" + trimmed + \"%\"}\n ORDER BY name\n LIMIT 5\n `);\n if (fuzzy.length === 1) {\n KNOWN_SERVER_NAMES.set(fuzzy[0]!.id, {\n id: fuzzy[0]!.id,\n name: fuzzy[0]!.name,\n });\n return fuzzy[0]!.id;\n }\n if (fuzzy.length === 0) {\n throw new Error(\n `Server \"${trimmed}\" not found by id or name. Call \\`list-servers\\` to see what's available.`,\n );\n }\n throw new Error(\n `Multiple servers match \"${trimmed}\": ${fuzzy.map((f) => f.name).join(\", \")}. Use an exact name or UUID.`,\n );\n}\n\n/**\n * Get connection options for a server. Every target except the SSH Proxy\n * itself is routed via ProxyJump through the proxy.\n *\n * Accepts either a UUID or a (fuzzy) server name — see `resolveServerId`.\n * Also returns the resolved `serverId` (canonical UUID) so callers that\n * need to cache per-server data don't have to call `resolveServerId` twice.\n *\n * Also returns the server's `os_type` so callers (notably ssh-execute) can\n * pick the right shell wrapper (bash vs PowerShell -EncodedCommand).\n */\nasync function getServerConnection(\n serverIdOrName: string,\n): Promise<{\n serverId: string;\n conn: SshConnectionOptions;\n proxy?: SshConnectionOptions;\n os: ServerOs;\n}> {\n const serverId = await resolveServerId(serverIdOrName);\n assertServerAccess(serverId);\n\n const rows = await db.execute<SshServerCredentialRow>(sql`\n SELECT\n ms.hostname,\n ms.port,\n ms.username,\n sc.password_encrypted,\n sc.ssh_key_encrypted,\n sc.ssh_key_passphrase_encrypted,\n ms.os AS os_type\n FROM managed_server ms\n LEFT JOIN server_credential sc ON sc.server_id = ms.id\n WHERE ms.id = ${serverId}\n LIMIT 1\n `);\n const data = rows[0];\n\n if (!data) {\n // Fuzzy hint based on the running cache of names. Helps when the LLM\n // typos a UUID or, more usefully, when a tool was somehow invoked with\n // a name string instead of an id.\n const candidates = Array.from(KNOWN_SERVER_NAMES.values()).flatMap((s) => [\n s.name,\n s.id,\n ]);\n const hits = suggestSimilar(serverId, candidates);\n const hint = hits.length ? ` Did you mean: ${hits.join(\", \")}?` : \"\";\n throw new Error(`Server not found: ${serverId}.${hint}`);\n }\n if (!encryptionKey)\n throw new Error(\"ENCRYPTION_KEY required to decrypt server credentials\");\n if (!data.password_encrypted && !data.ssh_key_encrypted) {\n throw new Error(\n `Server ${serverId} has no credentials in server_credential`,\n );\n }\n\n const conn: SshConnectionOptions = {\n hostname: data.hostname,\n port: data.port || 22,\n username: data.username,\n password: data.password_encrypted\n ? decrypt(data.password_encrypted)\n : undefined,\n privateKey: data.ssh_key_encrypted\n ? decrypt(data.ssh_key_encrypted)\n : undefined,\n passphrase: data.ssh_key_passphrase_encrypted\n ? decrypt(data.ssh_key_passphrase_encrypted)\n : undefined,\n };\n\n const needsProxy = serverId !== SSH_PROXY_SERVER_ID;\n const proxy = needsProxy ? await getProxyConnection() : undefined;\n const os: ServerOs =\n (data as { os_type?: string }).os_type === \"windows\" ? \"windows\" : \"linux\";\n\n return { serverId, conn, proxy, os };\n}\n\n/**\n * Execute an SSH command, optionally tunnelling through a proxy (ProxyJump).\n * When proxy is provided, the target server only sees the proxy's IP.\n *\n * `stdin` lets callers pipe data into the remote process (used by ssh-execute\n * smart mode + db-* helpers to avoid command-line escape hell with passwords,\n * SQL queries, scripts containing `$` or `#`, etc.).\n */\nasync function sshExec(\n opts: SshConnectionOptions,\n command: string,\n proxy?: SshConnectionOptions,\n options?: {\n stdin?: string;\n pty?: boolean;\n idleTimeoutMs?: number;\n noRetry?: boolean;\n },\n): Promise<SshResult> {\n // Single inline retry on transient failures (connect refused, DNS hiccup,\n // socket reset, etc). Eats 80% of \"errors\" in the wild without leaking the\n // distinction up to the LLM. Suppress with `noRetry: true` for non-idempotent\n // commands the caller wants to control.\n const first = await sshExecOnce(opts, command, proxy, options);\n if (options?.noRetry) return first;\n if (!isTransientSshError(first.stderr, first.exitCode)) return first;\n await new Promise((r) => setTimeout(r, 1000));\n const second = await sshExecOnce(opts, command, proxy, options);\n // Annotate stderr so debugging is obvious if the retry also fails.\n if (second.exitCode === -1 && second.stderr) {\n second.stderr = `[retry-1 also failed] ${second.stderr}`;\n }\n return second;\n}\n\nasync function sshExecOnce(\n opts: SshConnectionOptions,\n command: string,\n proxy?: SshConnectionOptions,\n options?: { stdin?: string; pty?: boolean; idleTimeoutMs?: number },\n): Promise<SshResult> {\n if (proxy) return sshExecViaProxy(proxy, opts, command, options);\n\n return new Promise((resolve) => {\n const ssh = new SshClient();\n let stdout = \"\";\n let stderr = \"\";\n let done = false;\n const wallTimeout = opts.timeout || 60_000;\n const idleTimeout = options?.idleTimeoutMs;\n\n const wallTimer = setTimeout(() => {\n if (!done) {\n done = true;\n clearTimeout(idleTimer);\n ssh.end();\n resolve({\n stdout,\n stderr: stderr || `idle/wall timeout after ${wallTimeout}ms`,\n exitCode: -1,\n });\n }\n }, wallTimeout);\n\n let idleTimer: NodeJS.Timeout | undefined;\n const armIdle = () => {\n if (!idleTimeout) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => {\n if (!done) {\n done = true;\n clearTimeout(wallTimer);\n ssh.end();\n resolve({\n stdout,\n stderr:\n stderr || `idle timeout after ${idleTimeout}ms with no output`,\n exitCode: -1,\n });\n }\n }, idleTimeout);\n };\n armIdle();\n\n ssh.on(\"ready\", () => {\n // Allocating a PTY collapses stderr into stdout (a real terminal has no\n // separate stderr fd) which is exactly what callers want for tty-mode\n // commands like `psql`/`mysql`/`bash`. Without pty: stderr is captured\n // separately so structured tools still get clean stderr.\n const execOpts = options?.pty ? { pty: true } : {};\n ssh.exec(command, execOpts, (err, stream) => {\n if (err) {\n if (!done) {\n done = true;\n clearTimeout(wallTimer);\n if (idleTimer) clearTimeout(idleTimer);\n ssh.end();\n resolve({ stdout, stderr: err.message || stderr, exitCode: -1 });\n }\n return;\n }\n stream.on(\"data\", (d: Buffer) => {\n stdout += d.toString();\n armIdle();\n });\n stream.stderr.on(\"data\", (d: Buffer) => {\n stderr += d.toString();\n armIdle();\n });\n stream.on(\"close\", (code: number | null) => {\n if (!done) {\n done = true;\n clearTimeout(wallTimer);\n if (idleTimer) clearTimeout(idleTimer);\n ssh.end();\n resolve({ stdout, stderr, exitCode: code ?? 0 });\n }\n });\n if (options?.stdin !== undefined) {\n stream.end(options.stdin);\n }\n });\n });\n\n ssh.on(\"error\", (err) => {\n if (!done) {\n done = true;\n clearTimeout(wallTimer);\n if (idleTimer) clearTimeout(idleTimer);\n resolve({ stdout, stderr: err.message, exitCode: -1 });\n }\n });\n\n ssh.connect({\n host: opts.hostname,\n port: opts.port,\n username: opts.username,\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n readyTimeout: wallTimeout,\n });\n });\n}\n\nfunction sshExecViaProxy(\n proxyOpts: SshConnectionOptions,\n targetOpts: SshConnectionOptions,\n command: string,\n options?: { stdin?: string; pty?: boolean; idleTimeoutMs?: number },\n): Promise<SshResult> {\n return new Promise((resolve) => {\n const proxyClient = new SshClient();\n let done = false;\n const wallTimeout = targetOpts.timeout || 60_000;\n const idleTimeout = options?.idleTimeoutMs;\n\n const wallTimer = setTimeout(() => {\n if (!done) {\n done = true;\n clearTimeout(idleTimer);\n proxyClient.end();\n resolve({\n stdout: \"\",\n stderr: \"SSH proxy command timeout\",\n exitCode: -1,\n });\n }\n }, wallTimeout);\n\n let idleTimer: NodeJS.Timeout | undefined;\n let stdoutBuf = \"\";\n let stderrBuf = \"\";\n const armIdle = () => {\n if (!idleTimeout) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => {\n if (!done) {\n done = true;\n clearTimeout(wallTimer);\n proxyClient.end();\n resolve({\n stdout: stdoutBuf,\n stderr:\n stderrBuf || `idle timeout after ${idleTimeout}ms with no output`,\n exitCode: -1,\n });\n }\n }, idleTimeout);\n };\n armIdle();\n\n const cleanup = () => {\n clearTimeout(wallTimer);\n if (idleTimer) clearTimeout(idleTimer);\n proxyClient.end();\n };\n\n proxyClient.on(\"ready\", () => {\n proxyClient.forwardOut(\n \"127.0.0.1\",\n 0,\n targetOpts.hostname,\n targetOpts.port,\n (err, tunnel) => {\n if (err) {\n if (!done) {\n done = true;\n cleanup();\n resolve({ stdout: \"\", stderr: err.message, exitCode: -1 });\n }\n return;\n }\n\n const targetClient = new SshClient();\n\n targetClient.on(\"ready\", () => {\n const execOpts = options?.pty ? { pty: true } : {};\n targetClient.exec(command, execOpts, (execErr, stream) => {\n if (execErr) {\n if (!done) {\n done = true;\n targetClient.end();\n cleanup();\n resolve({\n stdout: stdoutBuf,\n stderr: stderrBuf,\n exitCode: -1,\n });\n }\n return;\n }\n stream.on(\"data\", (d: Buffer) => {\n stdoutBuf += d.toString();\n armIdle();\n });\n stream.stderr.on(\"data\", (d: Buffer) => {\n stderrBuf += d.toString();\n armIdle();\n });\n stream.on(\"close\", (code: number | null) => {\n if (!done) {\n done = true;\n targetClient.end();\n cleanup();\n resolve({\n stdout: stdoutBuf,\n stderr: stderrBuf,\n exitCode: code ?? 0,\n });\n }\n });\n if (options?.stdin !== undefined) {\n stream.end(options.stdin);\n }\n });\n });\n\n targetClient.on(\"error\", (targetErr) => {\n if (!done) {\n done = true;\n targetClient.end();\n cleanup();\n resolve({\n stdout: stdoutBuf,\n stderr: targetErr.message,\n exitCode: -1,\n });\n }\n });\n\n targetClient.connect({\n sock: tunnel,\n username: targetOpts.username,\n password: targetOpts.password,\n privateKey: targetOpts.privateKey,\n passphrase: targetOpts.passphrase,\n readyTimeout: wallTimeout,\n });\n },\n );\n });\n\n proxyClient.on(\"error\", (err) => {\n if (!done) {\n done = true;\n cleanup();\n resolve({ stdout: \"\", stderr: err.message, exitCode: -1 });\n }\n });\n\n proxyClient.connect({\n host: proxyOpts.hostname,\n port: proxyOpts.port,\n username: proxyOpts.username,\n password: proxyOpts.password,\n privateKey: proxyOpts.privateKey,\n passphrase: proxyOpts.passphrase,\n readyTimeout: proxyOpts.timeout || 30_000,\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// Shared SSH connection helper (supports proxy tunnelling)\n// ---------------------------------------------------------------------------\n\nfunction connectSshClient(\n opts: SshConnectionOptions,\n proxy?: SshConnectionOptions,\n readyTimeout = 60_000,\n extraConnect?: { compress?: boolean | \"force\" },\n): Promise<{ client: SshClient; cleanup: () => void }> {\n const compress = extraConnect?.compress;\n if (!proxy) {\n return new Promise((resolve, reject) => {\n const ssh = new SshClient();\n ssh.on(\"ready\", () => resolve({ client: ssh, cleanup: () => ssh.end() }));\n ssh.on(\"error\", (e) => reject(e));\n ssh.connect({\n host: opts.hostname,\n port: opts.port,\n username: opts.username,\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n readyTimeout,\n ...(compress ? { compress } : {}),\n });\n });\n }\n\n return new Promise((resolve, reject) => {\n const proxyClient = new SshClient();\n\n proxyClient.on(\"ready\", () => {\n proxyClient.forwardOut(\n \"127.0.0.1\",\n 0,\n opts.hostname,\n opts.port,\n (err, tunnel) => {\n if (err) {\n proxyClient.end();\n reject(err);\n return;\n }\n\n const targetClient = new SshClient();\n targetClient.on(\"ready\", () =>\n resolve({\n client: targetClient,\n cleanup: () => {\n targetClient.end();\n proxyClient.end();\n },\n }),\n );\n targetClient.on(\"error\", (e) => {\n proxyClient.end();\n reject(e);\n });\n targetClient.connect({\n sock: tunnel,\n username: opts.username,\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n readyTimeout,\n ...(compress ? { compress } : {}),\n });\n },\n );\n });\n\n proxyClient.on(\"error\", (e) => reject(e));\n proxyClient.connect({\n host: proxy.hostname,\n port: proxy.port,\n username: proxy.username,\n password: proxy.password,\n privateKey: proxy.privateKey,\n passphrase: proxy.passphrase,\n readyTimeout: proxy.timeout || 30_000,\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// R2 (Cloudflare S3-compatible) helpers\n//\n// The four sftp-* tools route to R2 instead of an SSH server when the caller\n// passes `bucket: <name>`. Credentials come from env vars (R2_ENDPOINT +\n// R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY), so the MCP runs against any\n// Cloudflare R2 account without per-call config. The bucket *name* is part of\n// the call so the same MCP can address multiple buckets (backup, assets, etc.).\n// ---------------------------------------------------------------------------\n\nimport {\n AbortMultipartUploadCommand,\n type CommonPrefix,\n CompleteMultipartUploadCommand,\n CopyObjectCommand,\n CreateMultipartUploadCommand,\n DeleteObjectCommand,\n DeleteObjectsCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n PutObjectCommand,\n S3Client,\n UploadPartCommand,\n type _Object,\n} from \"@aws-sdk/client-s3\";\n\nlet _r2Client: S3Client | null = null;\n\nfunction getR2Client(): S3Client {\n if (_r2Client) return _r2Client;\n const endpoint = process.env.R2_ENDPOINT;\n const accessKeyId = process.env.R2_ACCESS_KEY_ID;\n const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;\n if (!endpoint || !accessKeyId || !secretAccessKey) {\n throw new Error(\n \"R2 not configured. Set R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY in the MCP env (mcp.json).\",\n );\n }\n _r2Client = new S3Client({\n region: \"auto\",\n endpoint,\n credentials: { accessKeyId, secretAccessKey },\n });\n return _r2Client;\n}\n\n/** Strip a leading `/` so callers can use familiar paths (`/foo/bar.txt`)\n * while R2 keys are stored without the slash (`foo/bar.txt`). */\nfunction r2Key(path: string): string {\n return path.replace(/^\\/+/, \"\");\n}\n\ninterface R2ListEntry {\n key: string;\n size: number;\n mtime: string;\n isPrefix: boolean;\n}\n\nasync function r2List(\n bucket: string,\n prefix: string,\n options: { recursive: boolean; maxResults: number },\n): Promise<R2ListEntry[]> {\n const client = getR2Client();\n const entries: R2ListEntry[] = [];\n let continuationToken: string | undefined;\n // Folder mode uses delimiter so we get CommonPrefixes (one entry per \"directory\").\n // Recursive mode omits delimiter and walks every key.\n const delimiter = options.recursive ? undefined : \"/\";\n\n do {\n const result = await client.send(\n new ListObjectsV2Command({\n Bucket: bucket,\n Prefix: prefix || undefined,\n Delimiter: delimiter,\n ContinuationToken: continuationToken,\n MaxKeys: Math.min(1000, options.maxResults - entries.length),\n }),\n );\n\n for (const cp of (result.CommonPrefixes || []) as CommonPrefix[]) {\n if (cp.Prefix)\n entries.push({ key: cp.Prefix, size: 0, mtime: \"\", isPrefix: true });\n if (entries.length >= options.maxResults) break;\n }\n for (const obj of (result.Contents || []) as _Object[]) {\n if (entries.length >= options.maxResults) break;\n entries.push({\n key: obj.Key || \"\",\n size: obj.Size || 0,\n mtime: obj.LastModified ? obj.LastModified.toISOString() : \"\",\n isPrefix: false,\n });\n }\n continuationToken = result.IsTruncated\n ? result.NextContinuationToken\n : undefined;\n } while (continuationToken && entries.length < options.maxResults);\n\n return entries;\n}\n\n/** Translate the aws-sdk's terse error names (\"NotFound\" / \"NoSuchKey\" /\n * \"UnknownError\") into actionable messages that include the bucket+key. */\nfunction r2WrapError(bucket: string, key: string, e: unknown): Error {\n const err = e as {\n name?: string;\n $metadata?: { httpStatusCode?: number };\n message?: string;\n };\n const status = err?.$metadata?.httpStatusCode;\n const name = err?.name || \"\";\n if (name === \"NoSuchKey\" || name === \"NotFound\" || status === 404) {\n return new Error(`r2://${bucket}/${key} not found`);\n }\n if (name === \"NoSuchBucket\")\n return new Error(`R2 bucket \"${bucket}\" not found`);\n if (status === 403 || name === \"AccessDenied\")\n return new Error(\n `Access denied for r2://${bucket}/${key} (check R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY)`,\n );\n return new Error(\n `R2 error (${name || \"unknown\"}${status ? ` ${status}` : \"\"}): ${err?.message || String(e)}`,\n );\n}\n\nasync function r2GetObject(\n bucket: string,\n key: string,\n maxBytes: number,\n): Promise<string> {\n const client = getR2Client();\n let size = 0;\n try {\n // Cheap HEAD first so we can refuse oversized objects without downloading them.\n const head = await client.send(\n new HeadObjectCommand({ Bucket: bucket, Key: key }),\n );\n size = head.ContentLength || 0;\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n if (size > maxBytes) {\n throw new Error(\n `Object too large: ${size} bytes (max ${maxBytes} for inline read; use sftp-write with sourcePath to mirror locally instead, or pass { offset, length } for a ranged read)`,\n );\n }\n try {\n const result = await client.send(\n new GetObjectCommand({ Bucket: bucket, Key: key }),\n );\n const body = result.Body as unknown as {\n transformToString?: () => Promise<string>;\n };\n if (!body?.transformToString)\n throw new Error(\"R2 returned no readable body\");\n return await body.transformToString();\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n}\n\nasync function r2GetObjectRange(\n bucket: string,\n key: string,\n range: { offset: number; length?: number },\n): Promise<string> {\n const client = getR2Client();\n let size = 0;\n try {\n const head = await client.send(\n new HeadObjectCommand({ Bucket: bucket, Key: key }),\n );\n size = head.ContentLength || 0;\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n if (range.offset >= size && size > 0)\n throw new Error(\n `offset ${range.offset} is past end of object (size ${size})`,\n );\n const MAX = 1_048_576;\n const remaining = Math.max(0, size - range.offset);\n const effectiveLen =\n range.length !== undefined\n ? Math.min(range.length, remaining, MAX)\n : Math.min(remaining, MAX);\n const end = range.offset + effectiveLen - 1;\n try {\n // S3 Range header is inclusive on both ends.\n const result = await client.send(\n new GetObjectCommand({\n Bucket: bucket,\n Key: key,\n Range: `bytes=${range.offset}-${end}`,\n }),\n );\n const body = result.Body as unknown as {\n transformToString?: () => Promise<string>;\n };\n if (!body?.transformToString)\n throw new Error(\"R2 returned no readable body\");\n const text = await body.transformToString();\n const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;\n return `${header}\\n${text}`;\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n}\n\nasync function r2PutObject(\n bucket: string,\n key: string,\n body: Buffer | Readable,\n contentLength?: number,\n): Promise<void> {\n const client = getR2Client();\n try {\n await client.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentLength: contentLength,\n ContentType: \"application/octet-stream\",\n }),\n );\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n}\n\nasync function r2DeleteObject(bucket: string, key: string): Promise<void> {\n const client = getR2Client();\n try {\n await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n}\n\n/** Delete all objects under a prefix. R2's DeleteObjects supports up to 1000\n * keys per request, so we loop list→delete in pages. Returns deleted count. */\nasync function r2DeletePrefix(bucket: string, prefix: string): Promise<number> {\n const client = getR2Client();\n let deleted = 0;\n let continuationToken: string | undefined;\n do {\n const list = await client.send(\n new ListObjectsV2Command({\n Bucket: bucket,\n Prefix: prefix,\n ContinuationToken: continuationToken,\n MaxKeys: 1000,\n }),\n );\n const keys = (list.Contents || [])\n .map((o) => o.Key)\n .filter((k): k is string => !!k);\n if (keys.length === 0) break;\n await client.send(\n new DeleteObjectsCommand({\n Bucket: bucket,\n Delete: { Objects: keys.map((k) => ({ Key: k })), Quiet: true },\n }),\n );\n deleted += keys.length;\n continuationToken = list.IsTruncated\n ? list.NextContinuationToken\n : undefined;\n } while (continuationToken);\n return deleted;\n}\n\n/** Multipart upload for files larger than ~4.5 GB (R2 single-PUT limit is 5 GB\n * with a safety margin). Streams the local file in 100 MB parts. */\nconst R2_MULTIPART_THRESHOLD = 4.5 * 1024 * 1024 * 1024; // 4.5 GB\nconst R2_MULTIPART_PART_SIZE = 100 * 1024 * 1024; // 100 MB\n\nasync function r2PutObjectMultipart(\n bucket: string,\n key: string,\n localPath: string,\n totalBytes: number,\n onProgress?: (bytes: number) => void,\n): Promise<void> {\n const client = getR2Client();\n const create = await client.send(\n new CreateMultipartUploadCommand({ Bucket: bucket, Key: key }),\n );\n const uploadId = create.UploadId;\n if (!uploadId)\n throw new Error(\"R2 returned no UploadId for multipart create\");\n\n const parts: { PartNumber: number; ETag: string }[] = [];\n try {\n let partNumber = 1;\n let uploaded = 0;\n let offset = 0;\n while (offset < totalBytes) {\n const end = Math.min(offset + R2_MULTIPART_PART_SIZE, totalBytes);\n // Read this part into memory (100 MB max). Streaming a single part with\n // unknown length is unreliable across SDK versions; buffering keeps us\n // simple and predictable.\n const chunk = await new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n const rs = createReadStream(localPath, { start: offset, end: end - 1 });\n rs.on(\"data\", (c: string | Buffer) => {\n chunks.push(typeof c === \"string\" ? Buffer.from(c) : c);\n });\n rs.on(\"end\", () =>\n resolve(Buffer.concat(chunks.map((b) => new Uint8Array(b)))),\n );\n rs.on(\"error\", reject);\n });\n const partResult = await client.send(\n new UploadPartCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n PartNumber: partNumber,\n Body: chunk,\n ContentLength: chunk.length,\n }),\n );\n if (!partResult.ETag)\n throw new Error(`Part ${partNumber} returned no ETag`);\n parts.push({ PartNumber: partNumber, ETag: partResult.ETag });\n uploaded += chunk.length;\n onProgress?.(uploaded);\n offset = end;\n partNumber++;\n }\n await client.send(\n new CompleteMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n MultipartUpload: { Parts: parts },\n }),\n );\n } catch (e) {\n // Best-effort abort to avoid orphaned parts (R2 charges for them).\n try {\n await client.send(\n new AbortMultipartUploadCommand({\n Bucket: bucket,\n Key: key,\n UploadId: uploadId,\n }),\n );\n } catch {\n /* ignore */\n }\n throw e;\n }\n}\n\n/** Server-side copy within R2 (same bucket or cross-bucket). No data egress. */\nasync function r2CopyObject(\n srcBucket: string,\n srcKey: string,\n dstBucket: string,\n dstKey: string,\n): Promise<{ size: number }> {\n const client = getR2Client();\n // We need the size for the response footer; HEAD it cheaply first.\n let size = 0;\n try {\n const head = await client.send(\n new HeadObjectCommand({ Bucket: srcBucket, Key: srcKey }),\n );\n size = head.ContentLength || 0;\n } catch (e) {\n throw r2WrapError(srcBucket, srcKey, e);\n }\n try {\n await client.send(\n new CopyObjectCommand({\n CopySource: encodeURIComponent(`${srcBucket}/${srcKey}`).replace(\n /%2F/g,\n \"/\",\n ),\n Bucket: dstBucket,\n Key: dstKey,\n }),\n );\n } catch (e) {\n throw r2WrapError(dstBucket, dstKey, e);\n }\n return { size };\n}\n\n/** Stream R2 GetObject body. Caller is responsible for consuming/destroying it. */\nasync function r2GetObjectStream(\n bucket: string,\n key: string,\n): Promise<{ stream: Readable; size: number }> {\n const client = getR2Client();\n let size = 0;\n try {\n const head = await client.send(\n new HeadObjectCommand({ Bucket: bucket, Key: key }),\n );\n size = head.ContentLength || 0;\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n try {\n const result = await client.send(\n new GetObjectCommand({ Bucket: bucket, Key: key }),\n );\n const body = result.Body as Readable | undefined;\n if (!body) throw new Error(\"R2 returned no readable body\");\n return { stream: body, size };\n } catch (e) {\n throw r2WrapError(bucket, key, e);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SFTP helpers\n// ---------------------------------------------------------------------------\n\nfunction sanitizePath(path: string): string {\n const normalized = path.replace(/\\\\/g, \"/\").replace(/\\0/g, \"\");\n const parts = normalized.split(\"/\");\n const resolved: string[] = [];\n for (const part of parts) {\n if (part === \"..\") {\n if (resolved.length > 0 && resolved[resolved.length - 1] !== \"\")\n resolved.pop();\n } else if (part !== \".\" && part !== \"\") resolved.push(part);\n }\n return \"/\" + resolved.join(\"/\");\n}\n\nconst PROTECTED_PATHS = [\n \"/etc/\",\n \"/boot/\",\n \"/usr/\",\n \"/bin/\",\n \"/sbin/\",\n \"/lib/\",\n \"/lib64/\",\n];\n\nfunction assertWritablePath(path: string): void {\n const safe = sanitizePath(path);\n for (const p of PROTECTED_PATHS) {\n if (safe === p.slice(0, -1) || safe.startsWith(p)) {\n throw new Error(`Write access denied to protected path: ${safe}`);\n }\n }\n}\n\n/** Convert a glob pattern (`*`, `?`, character classes) to a RegExp anchored\n * to the basename only. Used by sftp-list for filtering. */\nfunction globToRegExp(pattern: string): RegExp {\n let re = \"\";\n for (const c of pattern) {\n if (c === \"*\") re += \".*\";\n else if (c === \"?\") re += \".\";\n else if (/[.+^${}()|[\\]\\\\]/.test(c)) re += \"\\\\\" + c;\n else re += c;\n }\n return new RegExp(`^${re}$`);\n}\n\ninterface SftpEntry {\n kind: \"d\" | \"-\";\n size: number;\n mtime: string; // ISO; '' if unknown\n mtimeMs: number; // 0 if unknown; used for sorting\n path: string; // full or basename (depending on recursive mode)\n}\n\nasync function sftpReaddir(\n opts: SshConnectionOptions,\n dirPath: string,\n proxy?: SshConnectionOptions,\n options?: {\n recursive?: boolean;\n maxDepth?: number;\n pattern?: string;\n maxResults?: number;\n },\n): Promise<{ entries: SftpEntry[]; truncated: boolean; error?: string }> {\n const recursive = options?.recursive === true;\n const maxDepth = Math.max(1, Math.min(20, options?.maxDepth ?? 5));\n const maxResults = Math.max(\n 1,\n Math.min(50_000, options?.maxResults ?? 5_000),\n );\n const matcher = options?.pattern ? globToRegExp(options.pattern) : null;\n const rootSafe = sanitizePath(dirPath);\n\n let cleanup: (() => void) | undefined;\n try {\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\n cleanup = c;\n return await new Promise<{\n entries: SftpEntry[];\n truncated: boolean;\n error?: string;\n }>((resolve) => {\n const timer = setTimeout(() => {\n cleanup?.();\n resolve({ entries: [], truncated: false, error: \"timeout\" });\n cleanup = undefined;\n }, 60_000);\n\n client.sftp((err, sftp) => {\n if (err) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve({ entries: [], truncated: false, error: err.message });\n return;\n }\n\n const entries: SftpEntry[] = [];\n let truncated = false;\n const errors: string[] = [];\n\n const readOne = (path: string, depth: number): Promise<void> =>\n new Promise((resolveOne) => {\n sftp.readdir(path, (err2, list) => {\n if (err2) {\n errors.push(`error reading ${path}: ${err2.message}`);\n return resolveOne();\n }\n const subdirs: string[] = [];\n for (const item of list) {\n if (entries.length >= maxResults) {\n truncated = true;\n break;\n }\n const mode = item.attrs.mode || 0;\n const isDir = (mode & 0o170000) === 0o040000;\n const size = item.attrs.size || 0;\n const mtimeMs = item.attrs.mtime ? item.attrs.mtime * 1000 : 0;\n const mtime = mtimeMs ? new Date(mtimeMs).toISOString() : \"\";\n const fullPath =\n path === \"/\"\n ? `/${item.filename}`\n : `${path}/${item.filename}`;\n const include = !matcher || matcher.test(item.filename);\n if (include) {\n entries.push({\n kind: isDir ? \"d\" : \"-\",\n size,\n mtime,\n mtimeMs,\n path: recursive ? fullPath : item.filename,\n });\n }\n if (isDir && recursive && depth < maxDepth)\n subdirs.push(fullPath);\n }\n if (truncated || subdirs.length === 0) return resolveOne();\n // Walk subdirs sequentially to keep one SFTP session calm.\n (async () => {\n for (const sub of subdirs) {\n if (truncated) break;\n await readOne(sub, depth + 1);\n }\n resolveOne();\n })();\n });\n });\n\n readOne(rootSafe, 1).then(() => {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve({\n entries,\n truncated,\n error: errors.length ? errors.join(\"; \") : undefined,\n });\n });\n });\n });\n } catch (e: any) {\n cleanup?.();\n return { entries: [], truncated: false, error: e.message };\n }\n}\n\nasync function sftpRead(\n opts: SshConnectionOptions,\n filePath: string,\n proxy?: SshConnectionOptions,\n options?: { offset?: number; length?: number },\n): Promise<string> {\n const safe = sanitizePath(filePath);\n const offset = Math.max(0, Math.floor(options?.offset ?? 0));\n // Cap at 1 MiB regardless of how much the caller asks for; LLM context can't\n // sensibly absorb more than that and large reads should use SFTP→local file.\n const MAX = 1_048_576;\n const requestedLen =\n options?.length !== undefined\n ? Math.max(0, Math.floor(options.length))\n : undefined;\n\n let cleanup: (() => void) | undefined;\n try {\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000);\n cleanup = c;\n return await new Promise<string>((resolve) => {\n const timer = setTimeout(() => {\n cleanup?.();\n resolve(\"Error: timeout\");\n cleanup = undefined;\n }, 60_000);\n client.sftp((err, sftp) => {\n if (err) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(`Error: ${err.message}`);\n return;\n }\n sftp.stat(safe, (err2, stats) => {\n if (err2) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(`Error: ${err2.message}`);\n return;\n }\n const total = stats.size || 0;\n if (offset >= total && total > 0) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(\n `Error: offset ${offset} is past end of file (size ${total})`,\n );\n return;\n }\n const remaining = Math.max(0, total - offset);\n // Effective read length = caller-requested OR remaining-from-offset,\n // whichever is smaller, but never above MAX. In whole-file mode (no\n // offset/length) we still refuse files >MAX so the contract matches.\n const effectiveLen =\n requestedLen !== undefined\n ? Math.min(requestedLen, remaining, MAX)\n : Math.min(remaining, MAX);\n const isWholeFileRequest =\n options === undefined ||\n (offset === 0 && requestedLen === undefined);\n if (isWholeFileRequest && total > MAX) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(\n `Error: file too large (${total} bytes, max ${MAX}). Use { offset, length } for ranged reads.`,\n );\n return;\n }\n const chunks: Buffer[] = [];\n // ssh2 createReadStream supports `start` (inclusive) and `end` (inclusive).\n const rs = sftp.createReadStream(safe, {\n start: offset,\n end: offset + effectiveLen - 1,\n });\n rs.on(\"data\", (ch: Buffer) => chunks.push(ch));\n rs.on(\"end\", () => {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n const text = Buffer.concat(\n chunks.map((ch) => new Uint8Array(ch)),\n ).toString(\"utf-8\");\n // For ranged reads, prepend a one-line header so the LLM knows the\n // window. Whole-file reads stay unchanged for backwards compat.\n if (!isWholeFileRequest) {\n const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;\n resolve(`${header}\\n${text}`);\n } else {\n resolve(text);\n }\n });\n rs.on(\"error\", (e: Error) => {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(`Error: ${e.message}`);\n });\n });\n });\n });\n } catch (e: any) {\n cleanup?.();\n return `Error: ${e.message}`;\n }\n}\n\n// SFTP tuning. ssh2 fastPut uses 64 concurrent in-flight WRITE packets which\n// gives near-linerate throughput on modern OpenSSH (>= 8.6). The 64 KiB chunk\n// size is the safe upper bound for servers without the limits@openssh.com\n// extension; with it most OpenSSH builds happily accept up to 256 KiB.\nconst SFTP_FASTPUT_CONCURRENCY = 64;\nconst SFTP_FASTPUT_CHUNK_SIZE = 65_536;\n// Watchdog: kill the upload if no progress is observed for this long. Reset on\n// every fastPut step callback. Tighter than a wall-clock timeout because it\n// adapts to file size automatically.\nconst SFTP_IDLE_TIMEOUT_MS = 120_000;\n// Inline writes have no progress events, so we use a wall-clock cap.\nconst SFTP_INLINE_TIMEOUT_MS = 60_000;\nconst SFTP_PROGRESS_LOG_BYTES = 50 * 1024 * 1024;\n\nexport type SftpWriteInput = { content: string } | { sourcePath: string };\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;\n}\n\n// ---------------------------------------------------------------------------\n// Universal output processing (truncate, footer, fuzzy hints, cache, retry)\n// Applied centrally in handleCallTool so every tool benefits without per-case\n// boilerplate. Designed to be inert when not applicable (small outputs, etc).\n// ---------------------------------------------------------------------------\n\nconst RESPONSE_MAX_BYTES = 8192;\n\n// Sentinel used to suppress the response footer for tools that should stay raw\n// (e.g. things consumed verbatim by other tooling). None today, but the hook\n// is here so we can flag a tool name later via `NO_FOOTER_TOOLS.add('foo')`.\nconst NO_FOOTER_TOOLS = new Set<string>();\n\n// Tools that should be cached on the server side. Cache key is the tool name +\n// stable JSON of args (minus `noCache`). Set TTL to 0 to disable explicitly.\nconst TOOL_CACHE_TTL_MS: Record<string, number> = {\n \"list-servers\": 60_000,\n \"docker-list\": 30_000,\n};\n\ninterface CacheEntry {\n value: { content: { type: string; text: string }[] };\n expiresAt: number;\n}\nconst TOOL_CACHE = new Map<string, CacheEntry>();\n\nfunction cacheKeyFor(name: string, args: Record<string, unknown>): string {\n const { noCache: _ignored, ...rest } = args;\n void _ignored;\n // Stable stringify (sorted keys) so { a:1, b:2 } and { b:2, a:1 } collide.\n const sorted = Object.fromEntries(\n Object.entries(rest).sort(([a], [b]) => a.localeCompare(b)),\n );\n return `${name}::${JSON.stringify(sorted)}`;\n}\n\nfunction getCachedTool(\n name: string,\n args: Record<string, unknown>,\n): { content: { type: string; text: string }[] } | undefined {\n const ttl = TOOL_CACHE_TTL_MS[name];\n if (!ttl || ttl <= 0) return undefined;\n if (args.noCache === true) return undefined;\n const k = cacheKeyFor(name, args);\n const e = TOOL_CACHE.get(k);\n if (!e) return undefined;\n if (e.expiresAt < Date.now()) {\n TOOL_CACHE.delete(k);\n return undefined;\n }\n return e.value;\n}\n\nfunction setCachedTool(\n name: string,\n args: Record<string, unknown>,\n value: { content: { type: string; text: string }[] },\n): void {\n const ttl = TOOL_CACHE_TTL_MS[name];\n if (!ttl || ttl <= 0) return;\n if (args.noCache === true) return;\n TOOL_CACHE.set(cacheKeyFor(name, args), {\n value,\n expiresAt: Date.now() + ttl,\n });\n}\n\n// Fuzzy match: small Levenshtein for typo hints like \"Did you mean: foo?\".\n// Only used in error paths so the cost is irrelevant.\nfunction levenshtein(a: string, b: string): number {\n if (a === b) return 0;\n const m = a.length;\n const n = b.length;\n if (m === 0) return n;\n if (n === 0) return m;\n const dp: number[] = new Array(n + 1);\n for (let j = 0; j <= n; j++) dp[j] = j;\n for (let i = 1; i <= m; i++) {\n let prev = dp[0]!;\n dp[0] = i;\n for (let j = 1; j <= n; j++) {\n const tmp = dp[j]!;\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n dp[j] = Math.min(dp[j]! + 1, dp[j - 1]! + 1, prev + cost);\n prev = tmp;\n }\n }\n return dp[n]!;\n}\n\nfunction suggestSimilar(\n input: string,\n candidates: string[],\n max = 3,\n): string[] {\n if (!input || !candidates.length) return [];\n const lo = input.toLowerCase();\n const threshold = Math.max(2, Math.ceil(input.length / 3));\n return candidates\n .map((c) => ({ c, d: levenshtein(lo, c.toLowerCase()) }))\n .filter((x) => x.d <= threshold)\n .sort((a, b) => a.d - b.d)\n .slice(0, max)\n .map((x) => x.c);\n}\n\n// Lightweight running cache of recently-seen names. Populated by tools that\n// list things (servers, containers); consumed by tools that error on a name.\nconst KNOWN_SERVER_NAMES = new Map<string, { id: string; name: string }>(); // key=id\nconst KNOWN_CONTAINERS_BY_SERVER = new Map<\n string,\n { names: string[]; capturedAt: number }\n>();\n\nfunction rememberServers(servers: Array<{ id: string; name: string }>): void {\n for (const s of servers) KNOWN_SERVER_NAMES.set(s.id, s);\n}\nfunction rememberContainers(serverId: string, names: string[]): void {\n KNOWN_CONTAINERS_BY_SERVER.set(serverId, { names, capturedAt: Date.now() });\n}\n\n// Auto-context hints for list-servers: cheap pattern matching on tags +\n// hostnames so the LLM gets a 1-line \"what runs here\" summary on the first\n// listing call. Pure heuristics — no SSH probes.\nfunction buildServerContextHints(\n servers: Array<{ name: string; hostname: string; tags?: string[] | null }>,\n): string[] {\n const hints: string[] = [];\n for (const s of servers) {\n const tagSet = new Set<string>(\n (s.tags || []).map((t) => String(t).toLowerCase()),\n );\n const name = (s.name || \"\").toLowerCase();\n const host = (s.hostname || \"\").toLowerCase();\n const found: string[] = [];\n if (tagSet.has(\"trigger\") || /trigger/.test(name) || /trigger/.test(host))\n found.push(\"Trigger.dev self-hosted\");\n if (\n tagSet.has(\"supabase\") ||\n /supabase/.test(name) ||\n /supabase/.test(host)\n )\n found.push(\"Supabase stack\");\n if (tagSet.has(\"proxy\") || /proxy|jump/.test(name))\n found.push(\"SSH ProxyJump host\");\n if (tagSet.has(\"giga\") || /giga/.test(name)) found.push(\"shared workloads\");\n if (tagSet.has(\"vca\") || /vca/.test(name)) found.push(\"VCA hosting\");\n if (tagSet.has(\"mg-boilers\") || /boiler/.test(name))\n found.push(\"boiler API\");\n if (\n tagSet.has(\"refront\") ||\n /refront|tickets/.test(name) ||\n /refront|tickets/.test(host)\n )\n found.push(\"Refront/tickets\");\n if (found.length) hints.push(`- ${s.name}: ${found.join(\", \")}`);\n }\n return hints;\n}\nfunction getKnownContainers(\n serverId: string,\n maxAgeMs = 5 * 60_000,\n): string[] | undefined {\n const e = KNOWN_CONTAINERS_BY_SERVER.get(serverId);\n if (!e) return undefined;\n if (Date.now() - e.capturedAt > maxAgeMs) return undefined;\n return e.names;\n}\n\n// Truncate a text payload by UTF-8 byte budget, returning whether we cut.\nfunction truncateForLLM(\n text: string,\n maxBytes: number,\n): {\n text: string;\n truncated: boolean;\n totalBytes: number;\n shownBytes: number;\n} {\n const totalBytes = Buffer.byteLength(text, \"utf8\");\n if (totalBytes <= maxBytes)\n return { text, truncated: false, totalBytes, shownBytes: totalBytes };\n const buf = Buffer.from(text, \"utf8\");\n // Cut on a code-point boundary by scanning back from maxBytes to avoid\n // producing a broken multibyte sequence at the slice point.\n let cut = maxBytes;\n while (cut > 0 && (buf[cut]! & 0xc0) === 0x80) cut--;\n const head = buf.subarray(0, cut).toString(\"utf8\");\n return { text: head, truncated: true, totalBytes, shownBytes: cut };\n}\n\nfunction buildTruncationHint(\n name: string,\n args: Record<string, unknown>,\n total: number,\n shown: number,\n): string {\n const base = `(showing first ${shown} of ${total} bytes;`;\n if (name === \"sftp-read\") {\n const off = Number(args.offset) || 0;\n const next = off + shown;\n return `${base} pass { offset: ${next}, length: ${RESPONSE_MAX_BYTES} } to read more)`;\n }\n if (name === \"docker-logs\") {\n return `${base} use \\`tail\\`, \\`since\\`, or \\`grep\\` to narrow the window)`;\n }\n if (name === \"ssh-execute\") {\n return `${base} pipe through head/tail/grep server-side, or use sftp-read with offset for huge logs)`;\n }\n return `${base} narrow your query, paginate, or grep server-side to read the rest)`;\n}\n\n// Detect transient SSH/network failures worth a single retry. We're\n// intentionally conservative: only obvious connect-time hiccups, not generic\n// command failures (that would mask real bugs).\nconst TRANSIENT_RE =\n /(ECONNRESET|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|ENETUNREACH|EHOSTUNREACH|connection\\s+refused|connection\\s+reset|getaddrinfo|connect\\s+ETIMEDOUT|socket\\s+hang\\s*up|read\\s+ECONNRESET|All configured authentication methods failed)/i;\n\nfunction isTransientSshError(\n stderr: string | undefined,\n exitCode: number,\n): boolean {\n if (exitCode !== -1) return false;\n if (!stderr) return false;\n return TRANSIENT_RE.test(stderr);\n}\n\n// Result post-processing: cache write + truncate + footer. Pure function over\n// the result content. Idempotent for already-small outputs.\nfunction postprocessResult(\n result: { content: { type: string; text: string }[] },\n meta: {\n startedAtMs: number;\n serverIdLabel?: string;\n toolName: string;\n args: Record<string, unknown>;\n cached?: boolean;\n },\n): { content: { type: string; text: string }[] } {\n if (!result.content?.length) return result;\n const block = result.content[0]!;\n let text = String(block.text ?? \"\");\n\n const trunc = truncateForLLM(text, RESPONSE_MAX_BYTES);\n if (trunc.truncated) {\n text =\n trunc.text +\n \"\\n\\n... \" +\n buildTruncationHint(\n meta.toolName,\n meta.args,\n trunc.totalBytes,\n trunc.shownBytes,\n );\n }\n\n if (!NO_FOOTER_TOOLS.has(meta.toolName)) {\n const tookMs = Date.now() - meta.startedAtMs;\n const tookStr =\n tookMs < 1000 ? `${tookMs}ms` : `${(tookMs / 1000).toFixed(1)}s`;\n const sizeStr =\n trunc.totalBytes >= 1024\n ? `${(trunc.totalBytes / 1024).toFixed(1)} KB`\n : `${trunc.totalBytes} B`;\n const parts = [`took ${tookStr}`, sizeStr];\n if (meta.serverIdLabel) parts.push(`server: ${meta.serverIdLabel}`);\n if (meta.cached) parts.push(\"cached\");\n text = `${text}\\n\\n[${parts.join(\", \")}]`;\n }\n\n return { ...result, content: [{ ...block, text }] };\n}\n\n// ---------------------------------------------------------------------------\n// ssh-execute composition helpers (pipeline / repeat / format=ndjson)\n// ---------------------------------------------------------------------------\n\ninterface PipelineSegment {\n index: number;\n command: string;\n output: string;\n exitCode: number;\n}\ninterface IterationResult {\n index: number;\n startedAt: number;\n durationMs: number;\n result: SshResult;\n}\n\n// Build a wrapper script that runs N commands sequentially in a single SSH\n// session, with a unique marker between each so we can split outputs back\n// apart. Stderr is merged into stdout per command (so we can section it);\n// the original cumulative stderr stays available on the SshResult for diag.\nfunction buildPipelineScript(\n commands: string[],\n shell: \"bash\" | \"powershell\",\n marker: string,\n stopOnError: boolean,\n): string {\n if (shell === \"powershell\") {\n // PowerShell: redirect Error stream into Output (2>&1) per cmd, capture\n // $LASTEXITCODE after each. `iex` (Invoke-Expression) lets us run the\n // raw command strings without re-quoting.\n const lines: string[] = [\n \"$ErrorActionPreference='Continue'\",\n \"$ProgressPreference='SilentlyContinue'\",\n ];\n for (let i = 0; i < commands.length; i++) {\n lines.push(`Write-Output '${marker} ${i} begin'`);\n lines.push(`& { ${commands[i]} } 2>&1`);\n lines.push(\n `$__c = if ($null -eq $LASTEXITCODE) { 0 } else { $LASTEXITCODE }`,\n );\n lines.push(`Write-Output ('${marker} ' + ${i} + ' end exit=' + $__c)`);\n if (stopOnError) lines.push(`if ($__c -ne 0) { exit $__c }`);\n }\n return buildPowerShellEncodedCommand(lines.join(\"; \"), []);\n }\n // bash path: keep it portable so dash/sh works too. `set +e` per cmd\n // ensures continue-on-error mode actually continues even when the user's\n // script enables `set -e` somewhere inside.\n const sh: string[] = [];\n for (let i = 0; i < commands.length; i++) {\n sh.push(`echo \"${marker} ${i} begin\"`);\n sh.push(`{ ${commands[i]}; } 2>&1`);\n sh.push(`__c=$?`);\n sh.push(`echo \"${marker} ${i} end exit=$__c\"`);\n if (stopOnError) sh.push(`if [ \"$__c\" -ne 0 ]; then exit \"$__c\"; fi`);\n }\n return `bash -c ${posixQuote(sh.join(\"; \"))}`;\n}\n\n// Split a pipeline stdout payload back into per-command segments. Tolerates\n// missing markers (e.g. the script aborted mid-pipeline due to stop-on-error).\nfunction parsePipelineOutput(\n stdout: string,\n commands: string[],\n marker: string,\n): PipelineSegment[] {\n const segments: PipelineSegment[] = [];\n // Match `<marker> <i> begin` ... `<marker> <i> end exit=<code>` for each cmd.\n for (let i = 0; i < commands.length; i++) {\n const beginRe = new RegExp(\n `^${escapeRegex(marker)}\\\\s+${i}\\\\s+begin\\\\s*$`,\n \"m\",\n );\n const endRe = new RegExp(\n `^${escapeRegex(marker)}\\\\s+${i}\\\\s+end\\\\s+exit=(-?\\\\d+)\\\\s*$`,\n \"m\",\n );\n const beginMatch = beginRe.exec(stdout);\n const endMatch = endRe.exec(stdout);\n if (!beginMatch || !endMatch) {\n segments.push({\n index: i,\n command: commands[i] as string,\n output: \"(no output captured — pipeline aborted before this step?)\",\n exitCode: -1,\n });\n continue;\n }\n const start = beginMatch.index + beginMatch[0].length + 1; // +1 for newline\n const end = endMatch.index;\n const body = stdout.slice(start, end).replace(/\\n$/, \"\");\n const code = Number.parseInt(endMatch[1] as string, 10);\n segments.push({\n index: i,\n command: commands[i] as string,\n output: body,\n exitCode: Number.isFinite(code) ? code : -1,\n });\n }\n return segments;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction renderPipelineSegments(\n segments: PipelineSegment[],\n overall: SshResult,\n format: \"text\" | \"ndjson\",\n): string {\n const sections: string[] = [];\n for (const seg of segments) {\n sections.push(\n `>>> [${seg.index + 1}/${segments.length}] ${seg.command} (exit ${seg.exitCode})`,\n );\n let body = seg.output;\n if (format === \"ndjson\") {\n const parsed = tryParseNdjsonFromCommand(seg.command, body);\n if (parsed) body = parsed;\n }\n sections.push(body || \"(no output)\");\n }\n if (overall.stderr)\n sections.push(`--- aggregate stderr ---\\n${overall.stderr.trimEnd()}`);\n return sections.join(\"\\n\");\n}\n\nfunction renderRepeatResult(\n iters: IterationResult[],\n mode: \"all\" | \"diff\" | \"last\",\n format: \"text\" | \"ndjson\",\n): string {\n const formatBody = (s: string): string => {\n if (!format || format !== \"ndjson\") return s;\n // We don't know the original command here; try a heuristic parse anyway.\n return tryParseNdjsonFromCommand(\"\", s) || s;\n };\n if (mode === \"last\") {\n const last = iters[iters.length - 1]!;\n return `--- iteration ${last.index + 1}/${iters.length} (exit ${last.result.exitCode}, ${last.durationMs}ms) ---\\n${formatBody(last.result.stdout) || \"(empty)\"}${last.result.stderr ? `\\n[stderr] ${last.result.stderr.trimEnd()}` : \"\"}`;\n }\n if (mode === \"diff\") {\n const sections: string[] = [\n `(repeat: ${iters.length} runs, diff mode — only differences vs. previous run shown)`,\n ];\n let prev = \"\";\n for (let i = 0; i < iters.length; i++) {\n const cur = iters[i]!.result.stdout;\n if (i === 0) {\n sections.push(\n `--- iteration 1 (initial, ${iters[i]!.durationMs}ms) ---\\n${formatBody(cur) || \"(empty)\"}`,\n );\n } else {\n const changes = diffLines(prev, cur);\n const header = `--- iteration ${i + 1} (${iters[i]!.durationMs}ms, +${changes.added.length} -${changes.removed.length}) ---`;\n const block: string[] = [header];\n if (changes.added.length === 0 && changes.removed.length === 0) {\n block.push(\"(no changes)\");\n } else {\n for (const line of changes.added) block.push(`+ ${line}`);\n for (const line of changes.removed) block.push(`- ${line}`);\n }\n sections.push(block.join(\"\\n\"));\n }\n prev = cur;\n }\n return sections.join(\"\\n\");\n }\n // 'all'\n const sections: string[] = [`(repeat: ${iters.length} runs, all output)`];\n for (const it of iters) {\n sections.push(\n `--- iteration ${it.index + 1}/${iters.length} (exit ${it.result.exitCode}, ${it.durationMs}ms) ---`,\n );\n sections.push(formatBody(it.result.stdout) || \"(empty)\");\n if (it.result.stderr)\n sections.push(`[stderr] ${it.result.stderr.trimEnd()}`);\n }\n return sections.join(\"\\n\");\n}\n\nfunction diffLines(\n a: string,\n b: string,\n): { added: string[]; removed: string[] } {\n const aSet = new Set(a.split(\"\\n\"));\n const bSet = new Set(b.split(\"\\n\"));\n const added: string[] = [];\n const removed: string[] = [];\n for (const line of bSet) if (!aSet.has(line) && line) added.push(line);\n for (const line of aSet) if (!bSet.has(line) && line) removed.push(line);\n return { added, removed };\n}\n\n// NDJSON parser: detect common Linux command outputs from the command string\n// or content shape and emit one JSON object per record. Returns null if the\n// content doesn't look like a known format (caller falls back to raw text).\nfunction tryParseNdjsonFromCommand(\n command: string,\n stdout: string,\n): string | null {\n if (!stdout.trim()) return null;\n const c = command.toLowerCase();\n const looksLike = (re: RegExp) => re.test(c);\n // df -h / df -hT\n if (looksLike(/\\bdf\\b/) || /^Filesystem\\s+\\S+\\s+Used\\s+/m.test(stdout)) {\n return parseDf(stdout);\n }\n // free / free -m / free -h\n if (looksLike(/\\bfree\\b/) || /^\\s*total\\s+used\\s+free/m.test(stdout)) {\n return parseFree(stdout);\n }\n // ps aux / ps -ef\n if (looksLike(/\\bps\\b/) || /^USER\\s+PID\\s+%CPU\\s+%MEM/m.test(stdout)) {\n return parsePsAux(stdout);\n }\n // ss -tlnp / ss -tnlp / netstat -tlnp\n if (looksLike(/\\bss\\b/) || /^State\\s+Recv-Q\\s+Send-Q/m.test(stdout)) {\n return parseSs(stdout);\n }\n // lsblk\n if (looksLike(/\\blsblk\\b/) || /^NAME\\s+MAJ:MIN/m.test(stdout)) {\n return parseLsblk(stdout);\n }\n return null;\n}\n\nfunction splitCols(line: string, max?: number): string[] {\n const parts = line.trim().split(/\\s+/);\n if (max && parts.length > max) {\n return [...parts.slice(0, max - 1), parts.slice(max - 1).join(\" \")];\n }\n return parts;\n}\n\nfunction parseDf(s: string): string | null {\n const lines = s.split(\"\\n\").filter(Boolean);\n const header = lines[0];\n if (!header || !/Filesystem/i.test(header)) return null;\n // Normalise \"Mounted on\" → \"MountedOn\" before splitting, so we get a clean\n // single column instead of two (\"Mounted\" + \"on\" with empty value).\n const cleanHeader = header.replace(/Mounted on/i, \"MountedOn\");\n const cols = cleanHeader.trim().split(/\\s+/);\n const out: string[] = [];\n for (const ln of lines.slice(1)) {\n const parts = splitCols(ln, cols.length);\n if (parts.length < 4) continue;\n const obj: Record<string, string> = {};\n for (let i = 0; i < cols.length; i++)\n obj[cols[i] as string] = parts[i] || \"\";\n out.push(JSON.stringify(obj));\n }\n return out.length ? out.join(\"\\n\") : null;\n}\n\nfunction parseFree(s: string): string | null {\n const lines = s.split(\"\\n\").filter(Boolean);\n const out: string[] = [];\n for (const ln of lines) {\n if (/^\\s*total\\s+used\\s+free/i.test(ln)) continue;\n const m = ln.match(/^(\\S+):?\\s+(.+)$/);\n if (!m) continue;\n const [type, rest] = [m[1], m[2]];\n const cols = (rest as string).trim().split(/\\s+/);\n out.push(\n JSON.stringify({\n type: (type as string).replace(/:$/, \"\"),\n values: cols.map(Number),\n }),\n );\n }\n return out.length ? out.join(\"\\n\") : null;\n}\n\nfunction parsePsAux(s: string): string | null {\n const lines = s.split(\"\\n\").filter(Boolean);\n if (!lines[0] || !/USER\\s+PID/i.test(lines[0])) return null;\n const headers = lines[0].trim().split(/\\s+/);\n const out: string[] = [];\n for (const ln of lines.slice(1)) {\n const parts = splitCols(ln, headers.length);\n if (parts.length < headers.length) continue;\n const obj: Record<string, string> = {};\n for (let i = 0; i < headers.length; i++)\n obj[headers[i] as string] = parts[i] || \"\";\n out.push(JSON.stringify(obj));\n }\n return out.length ? out.join(\"\\n\") : null;\n}\n\nfunction parseSs(s: string): string | null {\n const lines = s.split(\"\\n\").filter(Boolean);\n if (!lines[0] || !/(State|Netid)/i.test(lines[0])) return null;\n const headers = lines[0].trim().split(/\\s+/);\n const out: string[] = [];\n for (const ln of lines.slice(1)) {\n const parts = splitCols(ln, headers.length);\n const obj: Record<string, string> = {};\n for (let i = 0; i < headers.length; i++)\n obj[headers[i] as string] = parts[i] || \"\";\n out.push(JSON.stringify(obj));\n }\n return out.length ? out.join(\"\\n\") : null;\n}\n\nfunction parseLsblk(s: string): string | null {\n const lines = s.split(\"\\n\").filter(Boolean);\n if (!lines[0] || !/NAME\\s+MAJ:MIN/i.test(lines[0])) return null;\n const headers = lines[0].trim().split(/\\s+/);\n const out: string[] = [];\n for (const ln of lines.slice(1)) {\n const parts = splitCols(ln, headers.length);\n const obj: Record<string, string> = {};\n for (let i = 0; i < headers.length; i++)\n obj[headers[i] as string] = parts[i] || \"\";\n out.push(JSON.stringify(obj));\n }\n return out.length ? out.join(\"\\n\") : null;\n}\n\n// Resolve a friendly server label for the response footer. Best-effort: falls\n// back to the bare ID if the server row isn't loaded into the cache yet.\nasync function resolveServerLabel(\n serverId: string | undefined,\n serverIds: unknown,\n): Promise<string | undefined> {\n if (Array.isArray(serverIds) && serverIds.length > 0)\n return `${serverIds.length} servers`;\n if (!serverId) return undefined;\n const cached = KNOWN_SERVER_NAMES.get(serverId);\n if (cached) return cached.name;\n try {\n const rows = await db.execute<SshServerNameRow>(sql`\n SELECT id, name FROM managed_server WHERE id = ${serverId} LIMIT 1\n `);\n const name = rows[0]?.name;\n if (name) {\n KNOWN_SERVER_NAMES.set(serverId, { id: serverId, name });\n return name;\n }\n } catch {\n /* swallow — footer is informational */\n }\n return serverId.slice(0, 8);\n}\n\nasync function sftpWrite(\n opts: SshConnectionOptions,\n filePath: string,\n input: SftpWriteInput,\n proxy?: SshConnectionOptions,\n meta?: { fileMode?: number; mtimeMs?: number },\n): Promise<string> {\n const safe = sanitizePath(filePath);\n assertWritablePath(safe);\n\n // File permission bits: caller may override (e.g. 0o755 for executable).\n // Default 0o644 keeps existing behaviour for plain config writes.\n const fileMode =\n meta?.fileMode !== undefined ? meta.fileMode & 0o7777 : 0o644;\n\n // Validate source up-front so the LLM gets a clear error before we open SSH.\n let mode: \"content\" | \"sourcePath\";\n let inlineBuffer: Buffer | undefined;\n let localPath: string | undefined;\n let expectedBytes = 0;\n\n if (\"content\" in input && typeof input.content === \"string\") {\n mode = \"content\";\n inlineBuffer = Buffer.from(input.content, \"utf-8\");\n expectedBytes = inlineBuffer.length;\n } else if (\"sourcePath\" in input && typeof input.sourcePath === \"string\") {\n mode = \"sourcePath\";\n localPath = input.sourcePath;\n if (!isAbsolute(localPath))\n return `Error: sourcePath must be an absolute path: ${localPath}`;\n if (!existsSync(localPath))\n return `Error: sourcePath does not exist: ${localPath}`;\n const st = statSync(localPath);\n if (!st.isFile())\n return `Error: sourcePath is not a regular file: ${localPath}`;\n expectedBytes = st.size;\n } else {\n return \"Error: sftp-write requires exactly one of: content (string) or sourcePath (absolute local path)\";\n }\n\n // For inline text we leave SSH compression enabled (cheap, often 5-10x for\n // configs/scripts). For sourcePath we disable it: large files are usually\n // already-compressed (zip/jpg/mp4/dump.gz) and SSH-level compression then\n // wastes CPU and slows the transfer.\n const compress = mode === \"content\";\n const startedAt = Date.now();\n let cleanup: (() => void) | undefined;\n\n try {\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 60_000, {\n compress,\n });\n cleanup = c;\n\n return await new Promise<string>((resolve) => {\n let resolved = false;\n let bytesWritten = 0;\n\n const finish = (msg: string) => {\n if (resolved) return;\n resolved = true;\n watchdog?.cancel();\n wallTimer && clearTimeout(wallTimer);\n cleanup?.();\n cleanup = undefined;\n resolve(msg);\n };\n\n // For sourcePath: idle watchdog reset on every fastPut step.\n // For content: simple wall-clock timeout.\n let watchdog: { reset: () => void; cancel: () => void } | undefined;\n let wallTimer: NodeJS.Timeout | undefined;\n\n if (mode === \"sourcePath\") {\n const armWatchdog = () => {\n let timer: NodeJS.Timeout = setTimeout(\n () =>\n finish(\n `Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`,\n ),\n SFTP_IDLE_TIMEOUT_MS,\n );\n return {\n reset: () => {\n clearTimeout(timer);\n timer = setTimeout(\n () =>\n finish(\n `Error: idle timeout (no SFTP progress for ${SFTP_IDLE_TIMEOUT_MS / 1000}s, wrote ${formatBytes(bytesWritten)} of ${formatBytes(expectedBytes)})`,\n ),\n SFTP_IDLE_TIMEOUT_MS,\n );\n },\n cancel: () => clearTimeout(timer),\n };\n };\n watchdog = armWatchdog();\n } else {\n wallTimer = setTimeout(\n () =>\n finish(`Error: timeout after ${SFTP_INLINE_TIMEOUT_MS / 1000}s`),\n SFTP_INLINE_TIMEOUT_MS,\n );\n }\n\n client.sftp((err, sftp) => {\n if (err) return finish(`Error: ${err.message}`);\n\n // Apply mtime after a successful write. SFTP `setstat` with atime+mtime\n // is the standard way; we leave atime equal to mtime (close enough for\n // tooling that cares about freshness). Errors are surfaced as a warning\n // suffix so the upload itself is still considered successful.\n const applyMtime = (then: (suffix: string) => void) => {\n if (meta?.mtimeMs === undefined) return then(\"\");\n const secs = Math.floor(meta.mtimeMs / 1000);\n sftp.setstat(safe, { atime: secs, mtime: secs }, (statErr) => {\n then(\n statErr\n ? ` (mtime set failed: ${statErr.message})`\n : ` (mtime=${new Date(meta.mtimeMs!).toISOString()})`,\n );\n });\n };\n\n if (mode === \"content\") {\n const ws = sftp.createWriteStream(safe, { mode: fileMode });\n ws.on(\"error\", (e: Error) => finish(`Error: ${e.message}`));\n ws.on(\"close\", () => {\n const elapsed = Date.now() - startedAt;\n applyMtime((suffix) =>\n finish(\n `Written ${expectedBytes} bytes to ${safe} in ${elapsed}ms (mode=0o${fileMode.toString(8)})${suffix}`,\n ),\n );\n });\n ws.end(inlineBuffer!);\n return;\n }\n\n // sourcePath path: ssh2 fastPut does the heavy lifting (parallel\n // pipelined SFTP_WRITE packets). Step callback gives us progress for\n // the watchdog and periodic logs.\n let nextProgressLog = SFTP_PROGRESS_LOG_BYTES;\n sftp.fastPut(\n localPath!,\n safe,\n {\n concurrency: SFTP_FASTPUT_CONCURRENCY,\n chunkSize: SFTP_FASTPUT_CHUNK_SIZE,\n mode: fileMode,\n fileSize: expectedBytes,\n step: (transferred: number) => {\n bytesWritten = transferred;\n watchdog?.reset();\n if (transferred >= nextProgressLog) {\n console.error(\n `[sftp-write] ${formatBytes(transferred)} / ${formatBytes(expectedBytes)} → ${safe}`,\n );\n nextProgressLog += SFTP_PROGRESS_LOG_BYTES;\n }\n },\n },\n (fpErr) => {\n if (fpErr) return finish(`Error: ${fpErr.message}`);\n const elapsed = Date.now() - startedAt;\n const mbps =\n expectedBytes / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\n applyMtime((suffix) =>\n finish(\n `Uploaded ${formatBytes(expectedBytes)} from ${localPath} to ${safe} ` +\n `in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s, mode=0o${fileMode.toString(8)})${suffix}`,\n ),\n );\n },\n );\n });\n });\n } catch (e: unknown) {\n cleanup?.();\n return `Error: ${e instanceof Error ? e.message : String(e)}`;\n }\n}\n\nasync function sftpDelete(\n opts: SshConnectionOptions,\n filePath: string,\n proxy?: SshConnectionOptions,\n options?: { recursive?: boolean },\n): Promise<string> {\n const safe = sanitizePath(filePath);\n assertWritablePath(safe);\n const recursive = options?.recursive === true;\n let cleanup: (() => void) | undefined;\n try {\n const { client, cleanup: c } = await connectSshClient(opts, proxy, 30_000);\n cleanup = c;\n return await new Promise<string>((resolve) => {\n const timer = setTimeout(() => {\n cleanup?.();\n resolve(\"Error: timeout\");\n cleanup = undefined;\n }, 60_000);\n client.sftp((err, sftp) => {\n if (err) {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(`Error: ${err.message}`);\n return;\n }\n\n // Recursive directory removal: walk the tree depth-first via SFTP and\n // unlink files / rmdir dirs from the bottom up. Pure SFTP — no shell\n // shenanigans, so it works on Windows OpenSSH too.\n if (recursive) {\n const removeTree = async (\n target: string,\n ): Promise<{ files: number; dirs: number }> => {\n return new Promise((resolveTree) => {\n sftp.stat(target, (statErr, stats) => {\n if (statErr) return resolveTree({ files: 0, dirs: 0 });\n const mode = stats.mode || 0;\n const isDir = (mode & 0o170000) === 0o040000;\n if (!isDir) {\n sftp.unlink(target, () => resolveTree({ files: 1, dirs: 0 }));\n return;\n }\n sftp.readdir(target, async (rdErr, list) => {\n if (rdErr) return resolveTree({ files: 0, dirs: 0 });\n let files = 0;\n let dirs = 0;\n for (const item of list) {\n const child =\n target === \"/\"\n ? `/${item.filename}`\n : `${target}/${item.filename}`;\n const r = await removeTree(child);\n files += r.files;\n dirs += r.dirs;\n }\n sftp.rmdir(target, () =>\n resolveTree({ files, dirs: dirs + 1 }),\n );\n });\n });\n });\n };\n removeTree(safe).then(({ files, dirs }) => {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(\n `Removed ${safe} recursively (${files} files, ${dirs} directories)`,\n );\n });\n return;\n }\n\n sftp.unlink(safe, (unlinkErr) => {\n if (unlinkErr) {\n sftp.rmdir(safe, (rmdirErr) => {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(\n rmdirErr\n ? `Error: ${unlinkErr.message}`\n : `Deleted directory ${safe}`,\n );\n });\n } else {\n clearTimeout(timer);\n cleanup?.();\n cleanup = undefined;\n resolve(`Deleted file ${safe}`);\n }\n });\n });\n });\n } catch (e: any) {\n cleanup?.();\n return `Error: ${e.message}`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cross-endpoint copy (SSH ↔ SSH, SSH ↔ R2, R2 ↔ R2). True streaming for\n// SSH paths so we never round-trip through local disk for huge files.\n// ---------------------------------------------------------------------------\n\nexport type CopyEndpoint =\n | {\n kind: \"ssh\";\n opts: SshConnectionOptions;\n proxy?: SshConnectionOptions;\n path: string;\n }\n | { kind: \"r2\"; bucket: string; key: string };\n\ninterface CopyResult {\n bytes: number;\n elapsedMs: number;\n mode: string;\n}\n\nasync function sftpCopy(\n src: CopyEndpoint,\n dst: CopyEndpoint,\n): Promise<CopyResult> {\n const startedAt = Date.now();\n\n // R2 → R2: server-side copy (zero data egress).\n if (src.kind === \"r2\" && dst.kind === \"r2\") {\n const { size } = await r2CopyObject(\n src.bucket,\n src.key,\n dst.bucket,\n dst.key,\n );\n return {\n bytes: size,\n elapsedMs: Date.now() - startedAt,\n mode: \"r2-server-side\",\n };\n }\n\n // R2 → SSH: stream R2 body into SFTP write stream.\n if (src.kind === \"r2\" && dst.kind === \"ssh\") {\n const safe = sanitizePath(dst.path);\n assertWritablePath(safe);\n const { stream, size } = await r2GetObjectStream(src.bucket, src.key);\n const { client, cleanup } = await connectSshClient(\n dst.opts,\n dst.proxy,\n 60_000,\n );\n try {\n await new Promise<void>((resolve, reject) => {\n client.sftp((err, sftp) => {\n if (err) return reject(err);\n const ws = sftp.createWriteStream(safe);\n ws.on(\"close\", () => resolve());\n ws.on(\"error\", reject);\n stream.on(\"error\", reject);\n stream.pipe(ws);\n });\n });\n } finally {\n cleanup();\n }\n return {\n bytes: size,\n elapsedMs: Date.now() - startedAt,\n mode: \"r2→ssh-stream\",\n };\n }\n\n // SSH → R2: pipe SFTP read stream to R2 PutObject. The S3 SDK accepts a\n // Readable body; ContentLength is required for R2's API, so we HEAD-equivalent\n // (sftp.stat) the source first.\n if (src.kind === \"ssh\" && dst.kind === \"r2\") {\n const safeSrc = sanitizePath(src.path);\n const { client, cleanup } = await connectSshClient(\n src.opts,\n src.proxy,\n 60_000,\n );\n try {\n const { stream, size } = await new Promise<{\n stream: Readable;\n size: number;\n }>((resolve, reject) => {\n client.sftp((err, sftp) => {\n if (err) return reject(err);\n sftp.stat(safeSrc, (statErr, stats) => {\n if (statErr) return reject(statErr);\n const s = (stats.size as number) || 0;\n const rs = sftp.createReadStream(safeSrc) as unknown as Readable;\n resolve({ stream: rs, size: s });\n });\n });\n });\n // For huge files (>4.5 GB) the single PUT path will fail (R2 limit).\n // We don't have multipart-from-stream right now, so fall back to a\n // clear error — caller can mirror locally first if needed.\n if (size > R2_MULTIPART_THRESHOLD) {\n cleanup();\n throw new Error(\n `Source object is ${formatBytes(size)} which exceeds R2 single-PUT cap (${formatBytes(R2_MULTIPART_THRESHOLD)}). For now: download via sftp-write { sourceRemote, target: local } first, then upload to R2 with sourcePath.`,\n );\n }\n await r2PutObject(dst.bucket, dst.key, stream, size);\n return {\n bytes: size,\n elapsedMs: Date.now() - startedAt,\n mode: \"ssh→r2-stream\",\n };\n } finally {\n cleanup();\n }\n }\n\n // SSH → SSH: open both sessions, pipe read stream into write stream. No\n // local detour — the SFTP protocol streams chunks directly.\n if (src.kind === \"ssh\" && dst.kind === \"ssh\") {\n const safeSrc = sanitizePath(src.path);\n const safeDst = sanitizePath(dst.path);\n assertWritablePath(safeDst);\n const srcConn = await connectSshClient(src.opts, src.proxy, 60_000);\n let dstConn: { client: SshClient; cleanup: () => void } | undefined;\n try {\n dstConn = await connectSshClient(dst.opts, dst.proxy, 60_000);\n const bytes = await new Promise<number>((resolve, reject) => {\n srcConn.client.sftp((err, srcSftp) => {\n if (err) return reject(err);\n dstConn!.client.sftp((err2, dstSftp) => {\n if (err2) return reject(err2);\n srcSftp.stat(safeSrc, (statErr, stats) => {\n if (statErr) return reject(statErr);\n const size = (stats.size as number) || 0;\n const rs = srcSftp.createReadStream(safeSrc);\n const ws = dstSftp.createWriteStream(safeDst);\n ws.on(\"close\", () => resolve(size));\n ws.on(\"error\", reject);\n rs.on(\"error\", reject);\n rs.pipe(ws);\n });\n });\n });\n });\n return {\n bytes,\n elapsedMs: Date.now() - startedAt,\n mode: \"ssh→ssh-stream\",\n };\n } finally {\n srcConn.cleanup();\n dstConn?.cleanup();\n }\n }\n\n throw new Error(\"Unsupported copy combination\");\n}\n\n// ---------------------------------------------------------------------------\n// Safety: dangerous command blocklist\n// ---------------------------------------------------------------------------\n\nconst BLOCKED_COMMANDS = [\n \"rm -rf /\",\n \"rm -fr /\",\n \"mkfs\",\n \"dd if=\",\n \":(){ :|:& };:\",\n \"shutdown\",\n \"halt\",\n \"init 0\",\n \"init 6\",\n \"> /dev/sda\",\n \"mv /* /dev/null\",\n \"chmod -R 000 /\",\n];\n\nfunction assertSafeCommand(command: string): void {\n const lower = command.toLowerCase().trim();\n for (const blocked of BLOCKED_COMMANDS) {\n if (lower.includes(blocked)) {\n throw new Error(`Blocked dangerous command pattern: \"${blocked}\"`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// MySQL / Database helpers\n// ---------------------------------------------------------------------------\n\ninterface DbCredentials {\n host: string;\n user: string;\n password: string;\n database: string;\n port: number;\n sitePath: string;\n appType: string;\n}\n\n/**\n * Discovers web applications under /var/www and extracts DB credentials\n * from their config files (WordPress, PrestaShop, Laravel, custom .env).\n */\nasync function discoverSiteDatabases(\n conn: SshConnectionOptions,\n proxy?: SshConnectionOptions,\n): Promise<DbCredentials[]> {\n const script = `\ncheck_dir() {\n local base=\"$1\" root=\"$2\"\n # WordPress\n if [ -f \"$root/wp-config.php\" ]; then\n echo \"WP|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\"\n return\n fi\n # PrestaShop 1.7+\n if [ -f \"$root/app/config/parameters.php\" ]; then\n echo \"PS|$base|$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)|$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\"\n return\n fi\n # PrestaShop 1.6\n if [ -f \"$root/config/settings.inc.php\" ]; then\n echo \"PS|$base|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)|$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\"\n return\n fi\n # Laravel / generic .env\n if [ -f \"$root/.env\" ]; then\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\n echo \"ENV|$base|$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)|$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\"\n return\n fi\n fi\n}\nfor dir in /var/www/*/; do\n [ -d \"$dir\" ] || continue\n check_dir \"$dir\" \"$dir\"\n # Also check common subdirectories: html, public_html, public, httpdocs\n for sub in html public_html public httpdocs; do\n [ -d \"$dir$sub\" ] && check_dir \"$dir\" \"$dir$sub\"\n done\ndone\n`.trim();\n\n const result = await sshExec(conn, script, proxy);\n const sites: DbCredentials[] = [];\n\n for (const line of result.stdout.split(\"\\n\")) {\n if (!line.trim()) continue;\n const parts = line.split(\"|\");\n if (parts.length < 6) continue;\n\n const [type, sitePath, database, user, password, host, port] = parts;\n if (!database || !user || !type || !sitePath) continue;\n\n const appTypes: Record<string, string> = {\n WP: \"WordPress\",\n PS: \"PrestaShop\",\n ENV: \"Laravel/.env\",\n };\n\n sites.push({\n appType: appTypes[type] || type,\n sitePath: sitePath.replace(/\\/$/, \"\"),\n database,\n user,\n password: password || \"\",\n host: host || \"localhost\",\n port: Number.parseInt(port || \"3306\", 10),\n });\n }\n\n return sites;\n}\n\nfunction escapeMysqlShell(value: string): string {\n return value.replace(/'/g, \"'\\\\''\");\n}\n\n// ---------------------------------------------------------------------------\n// Postgres container helpers (vanilla `postgres:*` / `pgvector/*` images)\n// ---------------------------------------------------------------------------\n\ninterface PostgresContainerInfo {\n container: string;\n db: string;\n user: string;\n hostPort: string | null;\n hasPassword: boolean;\n}\n\n/**\n * Enumerate running Docker containers that look like a vanilla Postgres\n * server: they expose `POSTGRES_USER` and `POSTGRES_DB` env vars (the\n * conventional credential carriers for `postgres:*` and `pgvector/*`\n * official images). Skips containers without those vars so Supabase-style\n * Postgres-inside-a-managed-stack containers aren't reported with garbage.\n */\nasync function discoverPostgresContainers(\n conn: SshConnectionOptions,\n proxy?: SshConnectionOptions,\n): Promise<PostgresContainerInfo[]> {\n // One round-trip: for every running container, dump env (silently skip\n // containers without /usr/bin/env) and the 5432 port mapping. Encode each\n // record as `PG|name|db|user|hasPass(0/1)|hostPort`.\n const script = `\ndocker ps --format '{{.Names}}' 2>/dev/null | while IFS= read -r name; do\n [ -n \"$name\" ] || continue\n envs=$(docker exec \"$name\" env 2>/dev/null | grep -E '^POSTGRES_(USER|DB|PASSWORD)=' || true)\n if [ -z \"$envs\" ]; then continue; fi\n user=$(printf '%s\\\\n' \"$envs\" | grep '^POSTGRES_USER=' | head -n1 | cut -d= -f2-)\n db=$(printf '%s\\\\n' \"$envs\" | grep '^POSTGRES_DB=' | head -n1 | cut -d= -f2-)\n if printf '%s\\\\n' \"$envs\" | grep -q '^POSTGRES_PASSWORD='; then hp=1; else hp=0; fi\n port=$(docker port \"$name\" 5432/tcp 2>/dev/null | head -n1 | awk -F: '{print $NF}')\n echo \"PG|$name|\\${db:-postgres}|\\${user:-postgres}|$hp|\\${port:-}\"\ndone\n`.trim();\n\n const result = await sshExec(conn, script, proxy);\n const out: PostgresContainerInfo[] = [];\n for (const line of result.stdout.split(\"\\n\")) {\n if (!line.startsWith(\"PG|\")) continue;\n const parts = line.split(\"|\");\n if (parts.length < 6) continue;\n const [, container, db, user, hasPass, hostPort] = parts;\n if (!container) continue;\n out.push({\n container,\n db: db || \"postgres\",\n user: user || \"postgres\",\n hostPort: hostPort || null,\n hasPassword: hasPass === \"1\",\n });\n }\n return out;\n}\n\n// Session-cache for per-container Postgres credentials. Keyed by\n// `${resolvedServerId}|${containerName}`. Primed eagerly by\n// `db-discover include=[\"postgres-containers\"]` and lazily by\n// `resolvePostgresContainerCreds` on a cache miss. TTL is 1h — container\n// env vars effectively never change, but we cap it so a recreated\n// container with new creds is picked up within reasonable time.\ninterface PostgresContainerCreds {\n dbName: string;\n dbUser: string;\n hasPassword: boolean;\n capturedAt: number;\n}\nconst POSTGRES_CONTAINER_CREDS_CACHE = new Map<\n string,\n PostgresContainerCreds\n>();\nconst PG_CREDS_TTL_MS = 60 * 60 * 1000;\n\nfunction cachePostgresContainerCreds(\n serverId: string,\n containerName: string,\n creds: Omit<PostgresContainerCreds, \"capturedAt\">,\n): void {\n POSTGRES_CONTAINER_CREDS_CACHE.set(`${serverId}|${containerName}`, {\n ...creds,\n capturedAt: Date.now(),\n });\n}\n\n/**\n * Look up the Postgres credentials (`POSTGRES_USER` / `POSTGRES_DB`) for a\n * container. Cached for an hour per (serverId, container). On a cache miss\n * does a single `docker exec <c> env | grep POSTGRES_` round-trip. Falls\n * back to `{ postgres, postgres }` if the container doesn't expose those\n * env vars — same defaults the rest of the code already uses.\n */\nasync function resolvePostgresContainerCreds(\n conn: SshConnectionOptions,\n proxy: SshConnectionOptions | undefined,\n serverId: string,\n containerName: string,\n): Promise<PostgresContainerCreds> {\n const key = `${serverId}|${containerName}`;\n const cached = POSTGRES_CONTAINER_CREDS_CACHE.get(key);\n if (cached && Date.now() - cached.capturedAt < PG_CREDS_TTL_MS) return cached;\n\n const safeContainer = containerName.replace(/[^a-zA-Z0-9._-]/g, \"\");\n const res = await sshExec(\n conn,\n `docker exec ${safeContainer} env 2>/dev/null | grep -E '^POSTGRES_(USER|DB|PASSWORD)='`,\n proxy,\n );\n\n let dbUser = \"postgres\";\n let dbName = \"postgres\";\n let hasPassword = false;\n for (const raw of res.stdout.split(\"\\n\")) {\n const line = raw.trim();\n if (line.startsWith(\"POSTGRES_USER=\"))\n dbUser = line.slice(\"POSTGRES_USER=\".length) || \"postgres\";\n else if (line.startsWith(\"POSTGRES_DB=\"))\n dbName = line.slice(\"POSTGRES_DB=\".length) || \"postgres\";\n else if (line.startsWith(\"POSTGRES_PASSWORD=\")) hasPassword = true;\n }\n\n const creds: PostgresContainerCreds = {\n dbName,\n dbUser,\n hasPassword,\n capturedAt: Date.now(),\n };\n POSTGRES_CONTAINER_CREDS_CACHE.set(key, creds);\n return creds;\n}\n\n// ---------------------------------------------------------------------------\n// Postgres migration ledger (`_mcp_migrations`)\n// ---------------------------------------------------------------------------\n\n/**\n * Pipe a SQL script into `psql` running inside a container. Used by both\n * db-apply-migration and db-list-migrations. Returns the raw stdout +\n * exit code so the caller can decide how to render errors. Adds\n * `ON_ERROR_STOP=1` so a failure inside a multi-statement script causes\n * a non-zero exit (otherwise psql just keeps going).\n */\nasync function psqlInContainer(\n conn: SshConnectionOptions,\n proxy: SshConnectionOptions | undefined,\n containerName: string,\n dbUser: string,\n dbName: string,\n scriptSql: string,\n flags: string,\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const safeContainer = containerName.replace(/[^a-zA-Z0-9._-]/g, \"\");\n const safeUser = dbUser.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n const safeDb = dbName.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n const cmd = `docker exec -i -e PGOPTIONS=--client-min-messages=warning ${safeContainer} psql -U ${safeUser} -d ${safeDb} -v ON_ERROR_STOP=1 -P pager=off ${flags}`;\n const res = await sshExec(conn, cmd, proxy, { stdin: scriptSql });\n return {\n stdout: res.stdout || \"\",\n stderr: res.stderr || \"\",\n exitCode: res.exitCode,\n };\n}\n\nconst MIGRATION_LEDGER_DDL = `\nCREATE TABLE IF NOT EXISTS _mcp_migrations (\n name TEXT PRIMARY KEY,\n sha256 TEXT NOT NULL,\n applied_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n applied_by TEXT\n);\n`.trim();\n\n/** Normalise SQL before hashing so a trailing newline doesn't trigger drift. */\nfunction normaliseMigrationSql(sql: string): string {\n return sql.replace(/\\r\\n/g, \"\\n\").trim() + \"\\n\";\n}\n\nfunction migrationSha256(sql: string): string {\n return createHash(\"sha256\")\n .update(normaliseMigrationSql(sql), \"utf8\")\n .digest(\"hex\");\n}\n\n/** Escape a value for inclusion inside a `$tag$ … $tag$` Postgres dollar-quoted string. */\nfunction dollarQuoteTag(value: string): string {\n // Find a tag not present in the value. `_mcp` is normally safe; if the\n // user pasted a literal `$_mcp$` (unlikely), step through numbered tags.\n let tag = \"_mcp\";\n let i = 0;\n while (value.includes(`$${tag}$`)) {\n i += 1;\n tag = `_mcp${i}`;\n }\n return tag;\n}\n\nfunction dollarQuote(value: string): string {\n const tag = dollarQuoteTag(value);\n return `$${tag}$${value}$${tag}$`;\n}\n\nconst BLOCKED_SQL_PATTERNS = [\n /\\bDROP\\s+DATABASE\\b/i,\n /\\bDROP\\s+TABLE\\b/i,\n /\\bDROP\\s+INDEX\\b/i,\n /\\bTRUNCATE\\b/i,\n /\\bALTER\\s+TABLE\\s+\\w+\\s+DROP\\b/i,\n /\\bDELETE\\s+FROM\\s+\\w+\\s*$/i,\n];\n\n/**\n * Build engine-specific schema-introspection SQL for the `describe` shortcut\n * on `db-query`. Sanitises the identifier so a caller can't slip an arbitrary\n * statement through `describe`. Pass \"*\" to list all tables in the current\n * database/schema.\n */\nfunction buildDescribeSql(\n target: string,\n engine: \"mysql\" | \"postgres\" | \"mssql\",\n): string {\n if (target === \"*\" || target === \"\") {\n if (engine === \"postgres\") {\n return \"SELECT schemaname, tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema') ORDER BY schemaname, tablename\";\n }\n if (engine === \"mssql\") {\n return \"SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' ORDER BY TABLE_SCHEMA, TABLE_NAME\";\n }\n return \"SHOW TABLES\";\n }\n const safe = target.replace(/[^a-zA-Z0-9_]/g, \"\");\n if (!safe) throw new Error(`Invalid describe target: ${target}`);\n if (engine === \"postgres\") {\n return (\n `SELECT column_name, data_type, is_nullable, column_default ` +\n `FROM information_schema.columns WHERE table_name='${safe}' ORDER BY ordinal_position;` +\n `\\nSELECT indexname, indexdef FROM pg_indexes WHERE tablename='${safe}'`\n );\n }\n if (engine === \"mssql\") {\n return `EXEC sp_help '${safe}'`;\n }\n return `DESCRIBE \\`${safe}\\`; SHOW INDEX FROM \\`${safe}\\``;\n}\n\n/**\n * Build the trailing diagnostic footer for `db-query` results so the caller\n * can tell whether the auto-LIMIT cap kicked in (and whether they should\n * paginate / refine) without having to count rows.\n */\nfunction formatDbQueryFooter(\n output: string,\n appliedLimit: boolean,\n maxRows: number,\n explainMode: boolean,\n): string {\n if (explainMode) {\n return \"\\n\\n[explain] Plan returned, no rows executed.\";\n }\n if (!appliedLimit) return \"\";\n\n // Prefer the trailing \"(N row(s))\" summary that psql/mysql/sqlcmd all emit;\n // falls back to counting non-decorative lines minus a presumed header row.\n // We over-fetched maxRows+1 internally so the printed count can briefly\n // equal maxRows+1 when truncation actually occurred.\n const rows = parseRowCountFromOutput(output);\n if (rows == null)\n return `\\n\\n[ok] auto-LIMIT ${maxRows} applied (row count not detected).`;\n if (rows > maxRows) {\n return `\\n\\n[truncated] auto-LIMIT ${maxRows} hit — more rows available. Refine WHERE / ORDER BY or raise maxRows (max 10000).`;\n }\n return `\\n\\n[ok] returned ${rows} row(s), under auto-LIMIT ${maxRows}.`;\n}\n\n/**\n * Best-effort row-count extractor for `db-query` output. Recognises the\n * `(N row[s])` summary line that psql / mysql / sqlcmd all print at the end\n * of a result set. Returns null if no recognizable summary is found, so the\n * caller can fall back to a less specific footer.\n */\nfunction parseRowCountFromOutput(output: string): number | null {\n // Walk lines bottom-up; the summary is typically the last non-empty line.\n const lines = output.split(\"\\n\");\n for (let i = lines.length - 1; i >= 0; i--) {\n const l = lines[i]?.trim();\n if (!l) continue;\n // postgres / mysql tabular: \"(5 rows)\" / \"(1 row)\"\n const m1 = /^\\(\\s*(\\d+)\\s+rows?\\s*\\)$/i.exec(l);\n if (m1?.[1]) return Number(m1[1]);\n // mysql shell: \"5 rows in set (..)\"\n const m2 = /^(\\d+)\\s+rows?\\s+in\\s+set\\b/i.exec(l);\n if (m2?.[1]) return Number(m2[1]);\n // mssql sqlcmd: \"(5 rows affected)\"\n const m3 = /^\\(\\s*(\\d+)\\s+rows?\\s+affected\\s*\\)$/i.exec(l);\n if (m3?.[1]) return Number(m3[1]);\n // Stop if we encounter a data row before any summary\n if (/[a-zA-Z0-9]/.test(l) && i < lines.length - 3) return null;\n }\n return null;\n}\n\nfunction assertSafeSql(query: string): void {\n const trimmed = query.trim();\n for (const pattern of BLOCKED_SQL_PATTERNS) {\n if (pattern.test(trimmed)) {\n throw new Error(`Blocked destructive SQL pattern: ${pattern.source}`);\n }\n }\n}\n\n/**\n * Builds a shell snippet that discovers DB credentials for a site path\n * and then executes a MySQL query, all in a single SSH session.\n */\nfunction buildSiteMysqlCommand(sitePath: string, query: string): string {\n const safePath = escapeMysqlShell(sitePath.replace(/\\/$/, \"\"));\n const safeQuery = escapeMysqlShell(query);\n\n return `\nSITE='${safePath}'\nDB_USER=\"\" DB_PASS=\"\" DB_NAME=\"\" DB_HOST=\"localhost\" DB_PORT=\"3306\"\nfor root in \"$SITE\" \"$SITE/html\" \"$SITE/public_html\" \"$SITE/public\" \"$SITE/httpdocs\"; do\n [ -d \"$root\" ] || continue\n if [ -f \"$root/wp-config.php\" ]; then\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_NAME'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_USER'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_PASSWORD'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'DB_HOST'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/wp-config.php\" 2>/dev/null)\n break\n elif [ -f \"$root/app/config/parameters.php\" ]; then\n DB_NAME=$(grep -oP \"'database_name'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\n DB_USER=$(grep -oP \"'database_user'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\n DB_PASS=$(grep -oP \"'database_password'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\n DB_HOST=$(grep -oP \"'database_host'\\\\s*=>\\\\s*'\\\\K[^']+\" \"$root/app/config/parameters.php\" 2>/dev/null)\n break\n elif [ -f \"$root/config/settings.inc.php\" ]; then\n DB_NAME=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_NAME_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\n DB_USER=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_USER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\n DB_PASS=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_PASSWD_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\n DB_HOST=$(grep -oP \"define\\\\s*\\\\(\\\\s*'_DB_SERVER_'\\\\s*,\\\\s*'\\\\K[^']+\" \"$root/config/settings.inc.php\" 2>/dev/null)\n break\n elif [ -f \"$root/.env\" ]; then\n DB_CONN=$(grep -oP '^DB_CONNECTION=\\\\K.*' \"$root/.env\" 2>/dev/null)\n if [ -n \"$DB_CONN\" ] && [ \"$DB_CONN\" != \"sqlite\" ]; then\n DB_NAME=$(grep -oP '^DB_DATABASE=\\\\K.*' \"$root/.env\" 2>/dev/null)\n DB_USER=$(grep -oP '^DB_USERNAME=\\\\K.*' \"$root/.env\" 2>/dev/null)\n DB_PASS=$(grep -oP '^DB_PASSWORD=\\\\K.*' \"$root/.env\" 2>/dev/null)\n DB_HOST=$(grep -oP '^DB_HOST=\\\\K.*' \"$root/.env\" 2>/dev/null)\n DB_PORT=$(grep -oP '^DB_PORT=\\\\K.*' \"$root/.env\" 2>/dev/null)\n break\n fi\n fi\ndone\n[ -z \"$DB_NAME\" ] || [ -z \"$DB_USER\" ] && echo \"ERROR: No database config found at $SITE\" && exit 1\nDB_HOST=\\${DB_HOST:-localhost}\nDB_PORT=\\${DB_PORT:-3306}\nmysql --user=\"$DB_USER\" --password=\"$DB_PASS\" --host=\"$DB_HOST\" --port=\"$DB_PORT\" -t -e '${safeQuery}' \"$DB_NAME\" 2>&1 | grep -v \"\\\\[Warning\\\\].*password\"\n`.trim();\n}\n\n/**\n * Execute a MySQL query for a site in a single SSH session.\n * Discovers credentials and runs the query in one command.\n */\nasync function execSiteMysql(\n conn: SshConnectionOptions,\n sitePath: string,\n query: string,\n proxy?: SshConnectionOptions,\n): Promise<string> {\n const cmd = buildSiteMysqlCommand(sitePath, query);\n const result = await sshExec(conn, cmd, proxy);\n const output = (result.stdout || \"\").trim();\n if (output.startsWith(\"ERROR: No database config found\")) {\n throw new Error(output);\n }\n if (result.exitCode !== 0 && !output) {\n throw new Error(result.stderr || \"MySQL command failed\");\n }\n return output;\n}\n\n// ---------------------------------------------------------------------------\n// mijn.host API helpers\n// ---------------------------------------------------------------------------\n\nconst MIJNHOST_BASE_URL = \"https://mijn.host/api/v2\";\n\ninterface MijnHostApiResponse<T = unknown> {\n status: number;\n status_description: string;\n data: T;\n}\n\nfunction requireMijnhostApiKey(): string {\n if (!mijnhostApiKey) {\n throw new Error(\n \"mijn.host API key not configured. Use --mijnhost-api-key=xxx or set MIJNHOST_API_KEY\",\n );\n }\n return mijnhostApiKey;\n}\n\ninterface DnsDiffRecord {\n type: string;\n name: string;\n value: string;\n ttl: number;\n}\n\n/**\n * Render a human-readable diff of a proposed DNS-zone change for `dryRun`\n * mode in dns-create / dns-update / dns-delete. Highlights added vs.\n * removed records and warns when the change touches MX / SPF / DKIM / DMARC\n * — historically the riskiest mistakes to commit blindly.\n */\nfunction formatDnsDiff(\n domain: string,\n before: DnsDiffRecord[],\n after: DnsDiffRecord[],\n change: {\n verb: \"create\" | \"update\" | \"delete\";\n added?: DnsDiffRecord[];\n removed?: DnsDiffRecord[];\n },\n): string {\n const fmt = (r: DnsDiffRecord): string =>\n `${r.type.padEnd(6)} ${r.name.padEnd(30)} ttl=${String(r.ttl).padEnd(5)} ${r.value}`;\n\n const lines: string[] = [];\n lines.push(\n `[dryRun] ${change.verb.toUpperCase()} on ${domain} — no changes applied.`,\n );\n lines.push(`Records before: ${before.length} → after: ${after.length}`);\n\n if (change.removed?.length) {\n lines.push(\"\", \"REMOVED:\");\n for (const r of change.removed) lines.push(` - ${fmt(r)}`);\n }\n if (change.added?.length) {\n lines.push(\"\", \"ADDED:\");\n for (const r of change.added) lines.push(` + ${fmt(r)}`);\n }\n\n const sensitive = [...(change.added ?? []), ...(change.removed ?? [])].filter(\n (r) => {\n if (r.type === \"MX\") return true;\n if (r.type === \"TXT\") {\n const v = r.value.toLowerCase();\n return (\n v.includes(\"v=spf1\") ||\n v.includes(\"v=dmarc1\") ||\n v.includes(\"_domainkey\") ||\n r.name.toLowerCase().includes(\"_domainkey\")\n );\n }\n return false;\n },\n );\n if (sensitive.length > 0) {\n lines.push(\n \"\",\n \"! WARNING: touches mail-auth records (MX / SPF / DMARC / DKIM). Double-check before re-running without dryRun.\",\n );\n }\n\n lines.push(\"\", \"Re-run without `dryRun: true` to apply.\");\n return lines.join(\"\\n\");\n}\n\n/**\n * Build a human-readable hint listing records that share the requested type +\n * name when `dns-record` update/delete fails to find an exact value match.\n * Greatly reduces the round-trip of: error → dns-list → retry.\n * Falls back to \"all records for this name\" when nothing matches type+name,\n * which catches typos in the type (e.g. CNAME vs ALIAS).\n */\nfunction describeDnsCandidates(\n records: DnsDiffRecord[],\n type: string,\n name: string,\n attemptedValue: string,\n): string {\n const sameTypeAndName = records.filter(\n (r) => r.type === type && r.name === name,\n );\n const fmt = (r: DnsDiffRecord): string =>\n ` - ${r.type.padEnd(6)} ${r.name.padEnd(30)} ttl=${String(r.ttl).padEnd(5)} ${r.value}`;\n\n if (sameTypeAndName.length > 0) {\n const lines = [\n \"Current records with this type + name (use one of these values verbatim):\",\n ];\n for (const r of sameTypeAndName.slice(0, 10)) lines.push(fmt(r));\n if (sameTypeAndName.length > 10)\n lines.push(` ...and ${sameTypeAndName.length - 10} more`);\n lines.push(`(attempted value: ${attemptedValue})`);\n return lines.join(\"\\n\");\n }\n\n // Type or name typo — show everything that matches just the name.\n const sameName = records.filter((r) => r.name === name);\n if (sameName.length > 0) {\n const types = [...new Set(sameName.map((r) => r.type))].sort().join(\", \");\n const lines = [\n `No ${type} records exist for \"${name}\", but other records do (types: ${types}). Sample:`,\n ];\n for (const r of sameName.slice(0, 10)) lines.push(fmt(r));\n if (sameName.length > 10)\n lines.push(` ...and ${sameName.length - 10} more`);\n return lines.join(\"\\n\");\n }\n\n return `No records found at all for name \"${name}\". Run dns-list to inspect the zone.`;\n}\n\nasync function mijnhostFetch<T>(\n path: string,\n options: RequestInit = {},\n): Promise<MijnHostApiResponse<T>> {\n const key = requireMijnhostApiKey();\n const headers: Record<string, string> = {\n \"API-Key\": key,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"mg-dashboard-mcp/6.6.3\",\n ...((options.headers as Record<string, string>) || {}),\n };\n const method = options.method ?? \"GET\";\n const requestBody =\n typeof options.body === \"string\"\n ? options.body\n : options.body != null\n ? String(options.body)\n : undefined;\n\n let status: number;\n let responseText: string;\n\n if (mijnhostViaSshProxy) {\n const proxy = await getProxyConnection();\n const proxied = await fetchViaSshProxy({\n proxy,\n url: `${MIJNHOST_BASE_URL}${path}`,\n method,\n headers,\n body: requestBody,\n timeoutMs: 60_000,\n });\n status = proxied.status;\n responseText = proxied.body;\n } else {\n const res = await fetch(`${MIJNHOST_BASE_URL}${path}`, {\n ...options,\n headers,\n });\n status = res.status;\n responseText = await res.text();\n }\n\n let json: unknown;\n try {\n json = JSON.parse(responseText);\n } catch {\n throw new Error(\n `mijn.host API returned non-JSON (${status}): ${responseText.slice(0, 300)}`,\n );\n }\n\n const body = json as MijnHostApiResponse<T>;\n if (status < 200 || status >= 300) {\n throw new Error(\n body?.status_description || `mijn.host API error: ${status}`,\n );\n }\n\n return body;\n}\n\n// ---------------------------------------------------------------------------\n// DNS zone serializer\n// ---------------------------------------------------------------------------\n// mijn.host's DNS API uses GET-then-PUT-the-whole-zone semantics, so two\n// concurrent `dns-record` calls for the same domain race: each one reads the\n// \"before\" zone, then PUTs its own derived \"after\" zone, and whichever PUT\n// wins last silently drops the other call's record. mijn.host also returns\n// transient 500s when called too fast back-to-back, which can leave the zone\n// in an unexpected partial state. We mitigate both by:\n// - Serializing all dns-record mutations per-domain through a chained Promise\n// - Waiting at least DNS_MIN_INTERVAL_MS between PUTs to the same zone\n// - Re-fetching the zone *inside* the lock so the diff is always against\n// the freshest state (not a stale snapshot from before the queue ran)\n// - Auto-retrying transient 5xx once after a short backoff\n// ---------------------------------------------------------------------------\n\nconst DNS_MIN_INTERVAL_MS = 750;\nconst DNS_RETRY_BACKOFF_MS = 1500;\nconst dnsZoneQueue: Map<string, Promise<unknown>> = new Map();\nconst dnsLastPutAt: Map<string, number> = new Map();\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Run `fn` exclusively for the given domain. Calls for the same domain queue\n * up; calls for different domains run in parallel. Enforces a minimum gap\n * between successive PUTs (recorded via `markDnsPut`) to avoid mijn.host\n * eventual-consistency glitches.\n */\nasync function withDnsZoneLock<T>(\n domain: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const key = domain.toLowerCase();\n const previous = dnsZoneQueue.get(key) ?? Promise.resolve();\n\n const run = previous.then(async () => {\n const last = dnsLastPutAt.get(key) ?? 0;\n const wait = DNS_MIN_INTERVAL_MS - (Date.now() - last);\n if (wait > 0) await sleep(wait);\n return fn();\n });\n\n // Always clear our slot once done so the map doesn't grow unbounded;\n // .catch chained on the queue entry (not the returned promise) prevents\n // unhandled-rejection warnings without swallowing the real error from `run`.\n const queued = run.finally(() => {\n if (dnsZoneQueue.get(key) === queued) dnsZoneQueue.delete(key);\n });\n dnsZoneQueue.set(\n key,\n queued.catch(() => {}),\n );\n\n return run;\n}\n\n/** Record a successful PUT so the next call for this domain waits enough. */\nfunction markDnsPut(domain: string): void {\n dnsLastPutAt.set(domain.toLowerCase(), Date.now());\n}\n\n/** True for transient mijn.host errors that are worth one retry. */\nfunction isTransientMijnhostError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return /Internal Server Error|API error: 5\\d\\d|fetch failed|ETIMEDOUT|ECONNRESET/i.test(\n msg,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Tool definitions\n// ---------------------------------------------------------------------------\n\nconst TOOLS = [\n {\n name: \"list-servers\",\n description:\n \"List all SSH servers you have access to. Returns id, name, hostname, tags, and os_type per server. \" +\n \"Pass `includeStats: true` to also probe each server in parallel for container count, disk-free, and uptime \" +\n \"(skips unreachable hosts gracefully). Cached for 60s — pass `noCache: true` to force a refresh. \" +\n 'Adds an \"auto-context\" footer with one-line tags inferred from server name/tags so the LLM knows which host runs Trigger / Supabase / proxy / etc. (disable with `context: false`).\\n\\n' +\n '**Tip:** every tool that takes `serverId` also accepts the server `name` directly (exact match or fuzzy `ILIKE %x%`). E.g. `ssh-execute serverId=\"MG Giga Server\"` works without a separate UUID lookup.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n includeStats: {\n type: \"boolean\",\n description:\n \"When true, probe each server (in parallel, with timeout) for container count, disk-free, and uptime.\",\n },\n statsParallelism: {\n type: \"number\",\n description:\n \"Max parallel probes when includeStats is true (default 8, cap 20).\",\n },\n statsTimeoutMs: {\n type: \"number\",\n description:\n \"Per-server probe timeout in ms when includeStats is true (default 6000, range 1000-30000).\",\n },\n context: {\n type: \"boolean\",\n description:\n \"Include auto-context footer with name/tag-based hints (default true). Pass false to suppress.\",\n },\n noCache: {\n type: \"boolean\",\n description: \"Bypass the 60s in-memory cache.\",\n },\n },\n },\n },\n {\n name: \"ssh-execute\",\n description:\n \"Execute one or more commands on a remote server via SSH. OS-aware: bash on linux, `powershell -EncodedCommand` (UTF-16LE base64) on windows, so $, #, quotes, spaces inside `args` are never re-interpreted by a shell. Some dangerous commands are blocked. Use `list-servers` first to see each server's os_type.\\n\\n\" +\n \"Three modes (compose them in one call):\\n\" +\n \"- Single: `command` (+ optional `args[]`). Quick or safe.\\n\" +\n '- Pipeline: `pipeline: [\"cmd1\",\"cmd2\",\"cmd3\"]` runs all commands sequentially in one SSH session and returns segmented per-command output (each with its own exit code). Default continues on error; pass `pipelineStopOnError: true` to abort.\\n' +\n '- Repeat: `repeat: N, intervalSeconds: S, output: \"all\"|\"diff\"|\"last\"`. Diff mode shows only added/removed lines vs. the previous run — perfect for \"watch this metric for 5 min\".\\n\\n' +\n \"`stdin` pipes data into the remote process (queries, scripts, secrets) without putting it on the command line. `cwd` sets the working directory (auto `cd` on Linux / `Set-Location` on Windows).\\n\\n\" +\n \"Idle timeout: defaults to 120s — if the remote produces no stdout/stderr for that long the call returns with a clear timeout message. Pass `idleTimeoutSeconds: 0` to disable, or e.g. `300` for slow workloads.\\n\\n\" +\n \"Fan-out: pass `serverIds: [id1, id2, ...]` (instead of `serverId`) to run across multiple servers in parallel.\\n\\n\" +\n 'Auto-features: outputs >8 KB are auto-truncated with a continuation hint; transient SSH failures (ECONNRESET/ETIMEDOUT/etc) get one automatic retry. Set `format: \"ndjson\"` to parse common Linux outputs (df / free / ps aux / ss / lsblk) into newline-delimited JSON instead of whitespace-padded text.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of one SSH server. Mutually exclusive with serverIds.\",\n },\n serverIds: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Fan-out: list of server UUIDs to run the command on in parallel. Mutually exclusive with serverId.\",\n },\n command: {\n type: \"string\",\n description:\n 'Program/command to run (e.g. \"mysql\", \"Get-Service\", \"df\"). Required unless `pipeline[]` is set.',\n },\n args: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional argv list. When provided, each entry is safely quoted/encoded for the target OS.\",\n },\n pipeline: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Run multiple shell commands sequentially in ONE SSH session, with per-command exit codes and segmented output. Saves N round-trips for setup→test→cleanup workflows.\",\n },\n pipelineStopOnError: {\n type: \"boolean\",\n description:\n \"When pipeline is set, abort the chain on the first non-zero exit (default false: keep going so all outputs reach the LLM).\",\n },\n repeat: {\n type: \"number\",\n description:\n 'Re-run the command/pipeline N times (default 1, max 60). Combine with intervalSeconds + output to \"watch\" a metric.',\n },\n intervalSeconds: {\n type: \"number\",\n description:\n \"When repeat>1, seconds to wait between iterations (default 0, max 600).\",\n },\n output: {\n type: \"string\",\n enum: [\"all\", \"diff\", \"last\"],\n description:\n \"When repeat>1: how to render iterations. `all` = full output per run; `diff` = only added/removed lines vs. previous run; `last` = only the final iteration.\",\n },\n format: {\n type: \"string\",\n enum: [\"text\", \"ndjson\"],\n description:\n \"Output format. `ndjson` parses common Linux outputs (df, free, ps aux, ss, lsblk) into newline-delimited JSON.\",\n },\n stdin: {\n type: \"string\",\n description: \"Optional data piped to the remote process stdin.\",\n },\n cwd: {\n type: \"string\",\n description:\n \"Working directory on the remote (cd <cwd> on Linux, Set-Location on Windows).\",\n },\n shell: {\n type: \"string\",\n enum: [\"auto\", \"bash\", \"powershell\"],\n description:\n 'Override shell selection (default \"auto\" uses the server\\'s os_type).',\n },\n parallelism: {\n type: \"number\",\n description:\n \"Max concurrent SSH sessions when using serverIds[] (default 5, max 20).\",\n },\n timeout: {\n type: \"number\",\n description:\n \"Wall timeout in milliseconds (default: 60000). Usually idleTimeoutSeconds is what you want instead.\",\n },\n idleTimeoutSeconds: {\n type: \"number\",\n description:\n 'Abort if no output for N seconds (default 120). Pass 0 to disable. Useful when the wall budget is hard to predict but silence usually means \"stuck\".',\n },\n },\n },\n },\n {\n name: \"sftp-list\",\n description:\n \"List files in remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n\" +\n '- `serverId`: list a directory on an SSH server via SFTP. Supports recursive traversal, depth cap, and glob filtering (no need for `ssh-execute \"find ...\"`).\\n' +\n \"- `bucket`: list objects in a Cloudflare R2 bucket. `path` becomes the key prefix. Default folder mode groups by `/` delimiter; pass `recursive: true` for a flat listing of all keys under the prefix. Requires R2_ENDPOINT, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY env vars on the MCP.\\n\\n\" +\n \"Sorting/summary applies to both backends: `sortBy` (name|size|mtime) + `reverse`. `summary: true` returns just totals (file count, dir count, total bytes) — useful as a cheap pre-flight before pulling a full listing.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of the SSH server (mutually exclusive with bucket)\",\n },\n bucket: {\n type: \"string\",\n description:\n \"Cloudflare R2 bucket name (mutually exclusive with serverId)\",\n },\n path: {\n type: \"string\",\n description: \"Directory path (SSH) or key prefix (R2). Default: /\",\n },\n recursive: {\n type: \"boolean\",\n description:\n \"Walk into subdirectories / list all keys flat (default false)\",\n },\n maxDepth: {\n type: \"number\",\n description:\n \"Maximum recursion depth for SSH mode (1-20, default 5). Ignored for R2.\",\n },\n pattern: {\n type: \"string\",\n description:\n 'Glob pattern to filter basenames (e.g. \"*.conf\", \"wp-*.php\").',\n },\n maxResults: {\n type: \"number\",\n description: \"Cap total entries returned (default 5000, max 50000)\",\n },\n sortBy: {\n type: \"string\",\n enum: [\"name\", \"size\", \"mtime\"],\n description:\n \"Sort order (default `name`). Directories always come first within each ordering.\",\n },\n reverse: {\n type: \"boolean\",\n description:\n \"Reverse sort direction (e.g. largest-first or newest-first).\",\n },\n summary: {\n type: \"boolean\",\n description:\n \"Return only totals (file count, directory count, total bytes) instead of the full listing.\",\n },\n },\n },\n },\n {\n name: \"sftp-read\",\n description:\n \"Read a text file from remote storage (max 1 MiB). Two backends (provide exactly one of `serverId` or `bucket`):\\n\" +\n \"- `serverId`: read from an SSH server via SFTP.\\n\" +\n \"- `bucket`: read an object from a Cloudflare R2 bucket. `path` is the object key.\\n\\n\" +\n \"Use `offset` and/or `length` for ranged reads — perfect for sampling a slice of a multi-MB log/dump without exceeding the 1 MiB inline limit. Ranged reads include a `# range: bytes A-B of TOTAL` header so you know what window you got.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of the SSH server (mutually exclusive with bucket)\",\n },\n bucket: {\n type: \"string\",\n description:\n \"Cloudflare R2 bucket name (mutually exclusive with serverId)\",\n },\n path: {\n type: \"string\",\n description: \"File path (SSH) or object key (R2)\",\n },\n offset: {\n type: \"number\",\n description:\n \"Byte offset to start reading from (0-indexed). Triggers ranged read mode.\",\n },\n length: {\n type: \"number\",\n description:\n \"Number of bytes to read (capped at 1 MiB). Defaults to remaining-from-offset when omitted.\",\n },\n },\n required: [\"path\"],\n },\n },\n {\n name: \"sftp-write\",\n description:\n \"Write OR copy a file in remote storage. Two target backends (`serverId` or `bucket`) and three source modes:\\n\\n\" +\n \"Sources:\\n\" +\n \"- `content` (string): inline UTF-8 text (≈1 MB max).\\n\" +\n \"- `sourcePath` (absolute local path): streams a local file. SSH uses ssh2 fastPut; R2 uses streamed PUT (or automatic multipart for >4.5 GB). Handles GB-scale.\\n\" +\n \"- `sourceRemote: { serverId|bucket, path }`: COPY mode — pulls from one remote and writes to another in a single operation, no local detour. Supports all four directions: ssh↔ssh, ssh↔r2, r2↔ssh, r2↔r2 (R2↔R2 uses server-side CopyObject = zero data egress).\\n\\n\" +\n \"Targets:\\n\" +\n \"- `serverId`: SSH server via SFTP. Protected system paths blocked. Optional `mode` (POSIX bits e.g. 0o755) and `mtime` (modification time) — SSH only.\\n\" +\n \"- `bucket`: Cloudflare R2 bucket. `mode`/`mtime` are ignored on R2.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"TARGET: UUID of the SSH server (mutually exclusive with bucket)\",\n },\n bucket: {\n type: \"string\",\n description:\n \"TARGET: Cloudflare R2 bucket name (mutually exclusive with serverId)\",\n },\n path: {\n type: \"string\",\n description: \"TARGET path (SSH file path or R2 object key)\",\n },\n content: {\n type: \"string\",\n description:\n \"Source: inline UTF-8 file content (mutually exclusive with sourcePath / sourceRemote)\",\n },\n sourcePath: {\n type: \"string\",\n description:\n \"Source: absolute local file path (mutually exclusive with content / sourceRemote). Use for >1 MB or binary.\",\n },\n sourceRemote: {\n type: \"object\",\n description:\n \"Source: copy from another remote. Shape: { serverId?: string, bucket?: string, path: string }. Picks the streaming strategy (ssh→ssh, r2→ssh, ssh→r2, r2→r2 server-side).\",\n properties: {\n serverId: { type: \"string\" },\n bucket: { type: \"string\" },\n path: { type: \"string\" },\n },\n },\n mode: {\n oneOf: [{ type: \"number\" }, { type: \"string\" }],\n description:\n 'POSIX file permission bits (SSH target only). Number (0o755 / 493) or octal string (\"755\" / \"0o755\"). Default 0o644.',\n },\n mtime: {\n oneOf: [{ type: \"number\" }, { type: \"string\" }],\n description:\n \"File modification time (SSH target only). ms-since-epoch number or ISO-8601 date string.\",\n },\n },\n required: [\"path\"],\n },\n },\n {\n name: \"sftp-delete\",\n description:\n \"Delete a file (or directory tree) from remote storage. Two backends (provide exactly one of `serverId` or `bucket`):\\n\" +\n \"- `serverId`: delete a file or empty directory on an SSH server via SFTP. Protected system paths blocked. With `recursive: true` walks the tree depth-first via SFTP and removes files + empty dirs from the bottom up (works on Windows OpenSSH too — no shell tricks).\\n\" +\n \"- `bucket`: delete an object from a Cloudflare R2 bucket. `path` is the object key. With `recursive: true`, treats `path` as a key prefix and batch-deletes every object beneath it.\\n\\n\" +\n \"Safety nets:\\n\" +\n '- `dryRun: true` → returns \"Would delete N items (size)\" with a sample preview, no actual deletion.\\n' +\n \"- `confirmAbove: N` + `confirmCount: <exact>` → refuses recursive deletes touching more than N items unless the caller passes `confirmCount` matching the actual count.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of the SSH server (mutually exclusive with bucket)\",\n },\n bucket: {\n type: \"string\",\n description:\n \"Cloudflare R2 bucket name (mutually exclusive with serverId)\",\n },\n path: {\n type: \"string\",\n description:\n \"File path / object key (or directory / key prefix when recursive)\",\n },\n recursive: {\n type: \"boolean\",\n description:\n \"Recursively remove a directory tree (SSH) or all objects under a key prefix (R2).\",\n },\n dryRun: {\n type: \"boolean\",\n description:\n \"Preview-only mode: returns what would be deleted (count, total size, sample paths) without touching anything.\",\n },\n confirmAbove: {\n type: \"number\",\n description:\n \"Refuse recursive deletes that touch more than N items unless `confirmCount` matches the actual count.\",\n },\n confirmCount: {\n type: \"number\",\n description:\n \"When confirmAbove gates a delete, pass the exact item count from the dry-run output to confirm intent.\",\n },\n },\n required: [\"path\"],\n },\n },\n {\n name: \"docker-list\",\n description:\n \"List Docker containers on one or more remote servers. Sorted by compose project then name, with a HEALTH column (healthy / unhealthy / starting / no-check). Filter by `nameFilter` (string OR array of substring/glob entries — passes if ANY entry matches), restrict to compose containers with `composeOnly`, or group output per project with `groupByProject`.\\n\\n\" +\n 'Fan-out: pass `serverIds: [...]` (instead of `serverId`) to query multiple servers in parallel — perfect for \"show all unhealthy containers across the fleet\". Per-server sections are clearly headed.\\n\\n' +\n \"Cached for 30s — pass `noCache: true` to bypass.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of one SSH server. Mutually exclusive with serverIds.\",\n },\n serverIds: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Fan-out: list of server UUIDs to query in parallel. Mutually exclusive with serverId.\",\n },\n format: {\n type: \"string\",\n enum: [\"table\", \"json\"],\n description:\n 'Output format: human table (default) or NDJSON. JSON adds a \"Server\" field per row in fan-out mode.',\n },\n composeOnly: {\n type: \"boolean\",\n description:\n \"Only show containers that have a docker-compose project label.\",\n },\n nameFilter: {\n oneOf: [\n { type: \"string\" },\n { type: \"array\", items: { type: \"string\" } },\n ],\n description:\n \"Filter by container name. Single entry or array; each entry is glob (* or ?) or substring. A row passes when ANY entry matches.\",\n },\n groupByProject: {\n type: \"boolean\",\n description:\n \"Group output per compose project with a `=== project (count) ===` header (single-server mode only).\",\n },\n parallelism: {\n type: \"number\",\n description:\n \"Max concurrent SSH sessions when using serverIds[] (default 5, max 20).\",\n },\n noCache: {\n type: \"boolean\",\n description: \"Bypass the 30s in-memory cache.\",\n },\n },\n },\n },\n {\n name: \"docker-logs\",\n description:\n \"Get logs from one or more Docker containers, optionally across multiple servers. `containerName` accepts a string OR array — multi-container output is line-prefixed with `[name]`. Supports time-window (`since`), server-side `grep`, line-count (`tail`), and real-time follow (`followSeconds`). Always merges stderr into stdout. Outputs >8 KB get a continuation hint.\\n\\n\" +\n \"Fan-out: pass `serverIds: [...]` to tail the same container(s) across multiple servers in one call (e.g. all kong instances). Per-server output is grouped under headers.\\n\\n\" +\n 'Fuzzy hint: if a container name typo is detected, the error includes \"Did you mean: ...\" suggestions from the docker-list cache.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description:\n \"UUID of one SSH server. Mutually exclusive with serverIds.\",\n },\n serverIds: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Fan-out: list of server UUIDs to tail in parallel. Mutually exclusive with serverId.\",\n },\n containerName: {\n oneOf: [\n { type: \"string\" },\n { type: \"array\", items: { type: \"string\" } },\n ],\n description:\n \"Single container name/ID or an array for multi-container tail. Multi mode prefixes each line with [name].\",\n },\n tail: {\n type: \"number\",\n description:\n \"Number of recent log lines per container (default 100, default 0 in follow mode).\",\n },\n lines: {\n type: \"number\",\n description: \"Deprecated alias for `tail`. Prefer `tail`.\",\n },\n since: {\n type: \"string\",\n description:\n 'Time window, e.g. \"10m\", \"2h\", \"24h\", or an absolute \"2026-05-09T10:00:00\".',\n },\n grep: {\n type: \"string\",\n description:\n \"Case-insensitive regex/literal filter applied server-side (saves tokens for noisy containers).\",\n },\n followSeconds: {\n type: \"number\",\n description:\n \"When >0, stream new log lines for N seconds via `docker logs -f`, then exit (max 300). Multi-container follow runs all streams in parallel.\",\n },\n parallelism: {\n type: \"number\",\n description:\n \"Max concurrent SSH sessions when using serverIds[] (default 5, max 20).\",\n },\n },\n required: [\"containerName\"],\n },\n },\n {\n name: \"docker-exec\",\n description:\n 'Run a command inside a running Docker container. `args[]` are quoted safely (no shell-escape hell with $ or quotes). Optional `stdin` pipes data into the container process (for SQL, scripts, etc.). Pass `interactive: true` to allocate a TTY (`docker exec -it`) so commands like `psql`/`mysql`/`bash` produce human-friendly output. Use this instead of `ssh-execute \"docker exec ...\"`.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: { type: \"string\", description: \"UUID of the SSH server\" },\n container: { type: \"string\", description: \"Container name or ID\" },\n command: {\n type: \"string\",\n description:\n 'Program to run inside the container (e.g. \"psql\", \"wp\", \"node\").',\n },\n args: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Argument list, each safely quoted.\",\n },\n stdin: {\n type: \"string\",\n description: \"Optional data piped to the container process stdin.\",\n },\n interactive: {\n type: \"boolean\",\n description:\n \"Allocate a TTY (`docker exec -it`). Useful for tools that probe isatty(stdout) — collapses stderr into stdout when enabled.\",\n },\n workdir: {\n type: \"string\",\n description: \"Working directory inside the container (-w).\",\n },\n user: {\n type: \"string\",\n description: \"User to run as inside the container (-u).\",\n },\n timeout: {\n type: \"number\",\n description: \"Timeout in milliseconds (default: 60000)\",\n },\n },\n required: [\"serverId\", \"container\", \"command\"],\n },\n },\n {\n name: \"docker-compose\",\n description:\n 'Run a docker-compose action against a project on a remote server. Replaces the common `ssh-execute \"cd /opt/x && docker compose ...\"` pattern. Action enum keeps the surface tiny.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: { type: \"string\", description: \"UUID of the SSH server\" },\n projectPath: {\n type: \"string\",\n description:\n \"Absolute path to the directory containing docker-compose.yml.\",\n },\n action: {\n type: \"string\",\n enum: [\"up\", \"down\", \"restart\", \"logs\", \"ps\", \"pull\", \"build\"],\n description: \"Compose action.\",\n },\n service: {\n type: \"string\",\n description:\n 'Optional service name to scope the action to (e.g. \"studio\"). Omit to act on the whole project.',\n },\n tail: {\n type: \"number\",\n description: \"For `logs`: number of lines (default 200).\",\n },\n timeout: {\n type: \"number\",\n description:\n \"Timeout in milliseconds (default: 120000 — compose ops can be slow).\",\n },\n },\n required: [\"serverId\", \"projectPath\", \"action\"],\n },\n },\n {\n name: \"wait-for\",\n description:\n \"Poll until a condition holds (or timeout). Replaces 30+ ad-hoc loops the LLM would otherwise build itself. Four condition types:\\n\" +\n '- `url`: `target: \"https://...\"`, `until: 200` (HTTP status, default 200). 10s per probe.\\n' +\n '- `container-health`: `serverId`, `target: \"container-name\"`, `until: \"healthy\" | \"running\" | \"exited\"` (default \"healthy\"). Uses `docker inspect`.\\n' +\n '- `file-exists`: `serverId`, `target: \"/path/to/file\"` — SSH stat check.\\n' +\n '- `sftp-exists`: same as file-exists but with `bucket: \"name\"` instead of serverId for R2.\\n\\n' +\n \"Returns a per-attempt trail so you can see how long it took to converge.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n type: {\n type: \"string\",\n enum: [\"url\", \"container-health\", \"file-exists\", \"sftp-exists\"],\n description: \"Condition type to wait on.\",\n },\n target: {\n type: \"string\",\n description:\n \"Target identifier: URL, container name, file path, or R2 key (depends on type).\",\n },\n until: {\n description:\n 'Expected end-state (depends on type): for url an HTTP status (default 200), for container-health a state string (default \"healthy\"). Omit for file-exists/sftp-exists.',\n },\n serverId: {\n type: \"string\",\n description:\n \"SSH server UUID (required for container-health and file-exists).\",\n },\n bucket: {\n type: \"string\",\n description:\n \"R2 bucket name (used with sftp-exists when checking an R2 object).\",\n },\n path: {\n type: \"string\",\n description: \"Alias for `target` for file-exists/sftp-exists.\",\n },\n intervalSeconds: {\n type: \"number\",\n description: \"Poll interval in seconds (default 3, max 60).\",\n },\n timeout: {\n type: \"number\",\n description: \"Total deadline in seconds (default 120, max 1800).\",\n },\n },\n required: [\"type\", \"target\"],\n },\n },\n {\n name: \"db-discover\",\n description:\n \"Discover databases available on an SSH server. Use this first to find what is reachable before running other db-* tools.\\n\\n\" +\n 'Modes (pass via `include` array, default `[\"www\"]`):\\n' +\n '- `\"www\"` — scan `/var/www` for WordPress / PrestaShop / Laravel / generic .env apps. Returns sitePath, db name, user, host, port.\\n' +\n '- `\"postgres-containers\"` — enumerate running Docker containers that expose `POSTGRES_USER` / `POSTGRES_DB` env vars (vanilla `postgres:*` / `pgvector/*` images). Returns container name, db, user, host port mapping, and whether a password is set. Use the returned (container, db, user) tuple directly with `db-query containerName=…` or `db-apply-migration`.\\n\\n' +\n 'Pass multiple modes to scan in parallel: `{ include: [\"www\", \"postgres-containers\"] }`.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: { type: \"string\", description: \"UUID of the SSH server\" },\n include: {\n type: \"array\",\n description:\n 'Which discovery modes to run. Defaults to `[\"www\"]` for back-compat. Add `\"postgres-containers\"` to enumerate vanilla Postgres Docker containers with their credentials.',\n items: { type: \"string\", enum: [\"www\", \"postgres-containers\"] },\n },\n },\n required: [\"serverId\"],\n },\n },\n {\n name: \"db-tables\",\n description:\n \"List tables with row counts + sizes. Two routing modes:\\n\" +\n \"- MySQL via `/var/www` autodiscover: pass `sitePath`. Credentials are read from wp-config.php / parameters.php / .env.\\n\" +\n \"- Postgres container: pass `containerName`. dbName + dbUser are auto-resolved from the container `POSTGRES_DB` / `POSTGRES_USER` env vars (cached 1h). Returns one row per user table sorted by total size, with estimated row count from pg_class.reltuples.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description: \"UUID or (fuzzy) name of the SSH server\",\n },\n sitePath: {\n type: \"string\",\n description:\n \"Site root path (e.g. /var/www/example.com). MySQL autodiscover mode.\",\n },\n containerName: {\n type: \"string\",\n description:\n \"Postgres container name. Activates direct Postgres mode.\",\n },\n dbName: {\n type: \"string\",\n description:\n \"Database name (containerName mode). Auto-resolved from container env when omitted.\",\n },\n dbUser: {\n type: \"string\",\n description:\n \"Database user (containerName mode). Auto-resolved from container env when omitted.\",\n },\n },\n required: [\"serverId\"],\n },\n },\n {\n name: \"db-query\",\n description:\n \"Execute SQL against any database. **Use this for ALL queries (SELECT, INSERT, UPDATE, DELETE, schema introspection) against vanilla Postgres / MySQL / MSSQL containers** — do NOT fall back to `ssh-execute` + `docker cp` + `psql -f` with .tmp.sql files; the container path here already pipes via stdin so quotes / `$` / `;` are safe. Multi-statement scripts work fine: separate with `;` and they will all be executed by psql/mysql.\\n\\n\" +\n \"Two routing modes:\\n\" +\n '- MySQL via `/var/www` autodiscover (default): pass `sitePath` (and `engine: \"mysql\"` implicitly). Credentials are read from wp-config.php, parameters.php, .env.\\n' +\n '- Direct via Docker container: pass `containerName` (the container running the DB server). Engine defaults to `postgres`; pass `engine: \"mysql\"` or `\"mssql\"` to override. Use `db-discover include=[\"postgres-containers\"]` to find available containers + creds.\\n\\n' +\n 'Postgres example: `{ serverId, containerName: \"refront-postgres-vanilla\", query: \"SELECT 1\" }` — dbName and dbUser are AUTO-RESOLVED from the container\\'s `POSTGRES_USER` / `POSTGRES_DB` env vars (cached 1h per server). Only pass `dbName`/`dbUser` explicitly when the instance hosts multiple databases or you want to query as a non-default role.\\n' +\n 'MSSQL example: `{ serverId, containerName: \"mssql-1\", engine: \"mssql\", dbUser: \"sa\", dbPass: \"...\", query: \"SELECT 1\" }`.\\n\\n' +\n \"Result safety: `maxRows` (default 1000, max 10000) auto-injects a `LIMIT` for SELECT queries that don't have one. The footer reports whether the cap was applied. Pass `maxRows: 0` to disable.\\n\\n\" +\n \"Diagnostics: `explain: true` prepends EXPLAIN (postgres / mysql) or runs `SET SHOWPLAN_TEXT ON` (mssql).\\n\\n\" +\n \"Atomic multi-statement: pass `transaction: true` to wrap the query in BEGIN/COMMIT (postgres / mysql) so a failure in any statement rolls back the lot. Use for ad-hoc fixes that are not schema migrations (e.g. `UPDATE tax_rate SET pct = pct * 100; UPDATE order SET ...`).\\n\\n\" +\n 'Schema introspection: pass `describe: \"tablename\"` to get columns + indexes (works for mysql, postgres, and mssql). Pass `describe: \"*\"` to list all tables. When `describe` is set, `query` is ignored.\\n\\n' +\n 'Destructive operations (DROP, TRUNCATE, ALTER … DROP, naked DELETE) are blocked by default. For schema migrations, **prefer `db-apply-migration`** — it has an audit ledger and idempotency. As an escape hatch for ad-hoc hot-fixes, pass `allowDestructive: \"yes-i-understand-this-is-not-logged\"` (literal string) to bypass the gate. The bypass is logged in the response footer.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: { type: \"string\", description: \"UUID of the SSH server\" },\n query: {\n type: \"string\",\n description:\n \"SQL query to execute (ignored when describe is set). Multiple statements separated by `;` are piped together to the client.\",\n },\n describe: {\n type: \"string\",\n description:\n 'Schema introspection shortcut. Pass a table name for columns + indexes, or \"*\" to list all tables. Works for mysql / postgres / mssql.',\n },\n sitePath: {\n type: \"string\",\n description:\n \"Site root path (e.g. /var/www/example.com). Used only with engine=mysql autodiscover.\",\n },\n containerName: {\n type: \"string\",\n description:\n 'Docker container running the DB server (e.g. \"refront-postgres-vanilla\", \"supabase-db\"). Activates direct-query mode.',\n },\n engine: {\n type: \"string\",\n enum: [\"mysql\", \"postgres\", \"mssql\"],\n description:\n 'DB engine. Defaults to \"mysql\" with sitePath, \"postgres\" with containerName.',\n },\n dbName: {\n type: \"string\",\n description:\n \"Database name (containerName mode). For postgres: auto-resolved from container `POSTGRES_DB` env var when omitted. For mysql: server default. For mssql: server default.\",\n },\n dbUser: {\n type: \"string\",\n description:\n 'Database user (containerName mode). For postgres: auto-resolved from container `POSTGRES_USER` env var when omitted. For mysql: defaults to \"root\". For mssql: defaults to \"sa\".',\n },\n dbPass: {\n type: \"string\",\n description:\n \"Database password (containerName mode). Required for mssql; optional for mysql; postgres uses trust auth by default.\",\n },\n maxRows: {\n type: \"number\",\n description:\n \"Auto-inject LIMIT for unbounded SELECTs. Default 1000, max 10000, set 0 to disable.\",\n },\n explain: {\n type: \"boolean\",\n description:\n \"Prepend EXPLAIN (postgres/mysql) or SHOWPLAN (mssql) instead of executing. Useful for slow-query diagnosis.\",\n },\n allowDestructive: {\n type: \"string\",\n description:\n 'Escape hatch for ad-hoc DROP/TRUNCATE/ALTER…DROP/naked DELETE. Pass the literal string \"yes-i-understand-this-is-not-logged\". For schema migrations prefer db-apply-migration (audit-logged, idempotent).',\n },\n transaction: {\n type: \"boolean\",\n description:\n \"Wrap the query in BEGIN/COMMIT so multiple statements either all succeed or all roll back. Use for atomic ad-hoc updates like `UPDATE x SET y = y * 100; UPDATE z ...` that are not migration-worthy. Ignored in EXPLAIN mode and on MSSQL (use its own transaction syntax). Postgres/MySQL only.\",\n },\n },\n required: [\"serverId\"],\n },\n },\n {\n name: \"db-apply-migration\",\n description:\n \"Apply a SQL migration to a Postgres container and record it in an MCP-managed ledger table (`_mcp_migrations`) so re-runs are idempotent. Use this for ALL schema changes (CREATE/ALTER/DROP/TRUNCATE) — it allows DDL that `db-query` blocks, and gives you audit + drift detection in exchange.\\n\\n\" +\n \"Ledger schema (auto-created on first call): `_mcp_migrations(name TEXT PRIMARY KEY, sha256 TEXT, applied_at TIMESTAMPTZ, applied_by TEXT)`.\\n\\n\" +\n \"Behaviour:\\n\" +\n '- If `name` is already in the ledger AND the sha256 of the supplied SQL matches → no-op, returns \"already applied\".\\n' +\n '- If `name` is already in the ledger with a DIFFERENT sha256 → fails loudly (\"drift detected\"). Pass `force: true` to overwrite (logged).\\n' +\n \"- Otherwise the SQL is wrapped in BEGIN/COMMIT and applied, then a row is inserted into `_mcp_migrations`.\\n\\n\" +\n \"Pass `noTransaction: true` for statements that cannot run inside a transaction (`CREATE INDEX CONCURRENTLY`, `ALTER TYPE … ADD VALUE`, `VACUUM`, etc.). In that mode the user SQL runs first and the ledger is recorded in a separate follow-up call.\\n\\n\" +\n \"SQL source: provide ONE of `sql` (inline string), `localFile` (path on this machine, read and piped via stdin), or `remoteFile` (absolute path on the SSH server, read with `cat` first).\\n\\n\" +\n 'Example: `{ serverId, containerName: \"refront-postgres-vanilla\", name: \"20260517120000_add_unified_classification\", localFile: \"./migrations/20260517120000_add_unified_classification.sql\" }` — dbName + dbUser are auto-resolved from the container env (cached 1h).',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description: \"UUID or (fuzzy) name of the SSH server\",\n },\n containerName: {\n type: \"string\",\n description:\n 'Postgres container name (e.g. \"refront-postgres-vanilla\")',\n },\n dbName: {\n type: \"string\",\n description:\n \"Database. Auto-resolved from container `POSTGRES_DB` env when omitted. Override only when the instance hosts multiple databases.\",\n },\n dbUser: {\n type: \"string\",\n description:\n \"User. Auto-resolved from container `POSTGRES_USER` env when omitted.\",\n },\n name: {\n type: \"string\",\n description:\n \"Unique migration name (recommended format: `YYYYMMDDhhmmss_description`)\",\n },\n sql: {\n type: \"string\",\n description:\n \"Inline SQL string (mutually exclusive with localFile / remoteFile)\",\n },\n localFile: {\n type: \"string\",\n description:\n \"Path on this machine to a .sql file (read here, streamed via stdin)\",\n },\n remoteFile: {\n type: \"string\",\n description:\n \"Absolute path of a .sql file already on the server (read with `cat`)\",\n },\n noTransaction: {\n type: \"boolean\",\n description:\n \"Skip the implicit BEGIN/COMMIT wrapper. Required for CONCURRENTLY / ALTER TYPE ADD VALUE / VACUUM. Default false.\",\n },\n force: {\n type: \"boolean\",\n description:\n \"Re-apply even when the ledger says it ran with a different sha256. Use after a deliberate edit; logged in the response.\",\n },\n recordOnly: {\n type: \"boolean\",\n description:\n \"Register the migration in the ledger WITHOUT executing the SQL. Use to backfill migrations that were applied out-of-band (e.g. by hand via ssh + psql). The SQL is still required so the recorded sha256 matches what was run.\",\n },\n },\n required: [\"serverId\", \"containerName\", \"name\"],\n },\n },\n {\n name: \"db-list-migrations\",\n description:\n 'List entries from the `_mcp_migrations` ledger on a Postgres container. Answers \"what migrations have already been applied here?\" without having to write SQL. Returns full name, sha256, applied_at, applied_by, ordered by most recent first. If the ledger table does not exist yet (no migrations applied via db-apply-migration), returns a friendly empty response. dbName + dbUser are auto-resolved from the container env when omitted.',\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: {\n type: \"string\",\n description: \"UUID or (fuzzy) name of the SSH server\",\n },\n containerName: {\n type: \"string\",\n description: \"Postgres container name\",\n },\n dbName: {\n type: \"string\",\n description:\n \"Database. Auto-resolved from container `POSTGRES_DB` env when omitted.\",\n },\n dbUser: {\n type: \"string\",\n description:\n \"User. Auto-resolved from container `POSTGRES_USER` env when omitted.\",\n },\n limit: {\n type: \"number\",\n description: \"Max number of entries (default 50, max 500)\",\n },\n },\n required: [\"serverId\", \"containerName\"],\n },\n },\n {\n name: \"env-list\",\n description:\n \"List all stored environment configurations with their release profile names.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n releaseProfile: {\n type: \"string\",\n description:\n \"Release profile name to filter by (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Omit to list all.\",\n },\n },\n },\n },\n {\n name: \"env-get\",\n description:\n \"Retrieve the decrypted .env content for a specific app and environment.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n appName: {\n type: \"string\",\n description: \"Application name (e.g. backoffice, api, web)\",\n },\n environment: {\n type: \"string\",\n enum: [\"production\", \"staging\", \"development\", \"local\"],\n description: \"Environment name\",\n },\n releaseProfile: {\n type: \"string\",\n description:\n \"Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.\",\n },\n },\n required: [\"appName\", \"environment\"],\n },\n },\n {\n name: \"env-store\",\n description:\n \"Store or update an encrypted .env configuration for an app and environment.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n appName: {\n type: \"string\",\n description: \"Application name (e.g. backoffice, api, web)\",\n },\n environment: {\n type: \"string\",\n enum: [\"production\", \"staging\", \"development\", \"local\"],\n description: \"Environment name\",\n },\n content: {\n type: \"string\",\n description: \"The .env file content to store\",\n },\n description: { type: \"string\", description: \"Optional description\" },\n releaseProfile: {\n type: \"string\",\n description:\n \"Release profile name (usually matches the project folder name or git repo name, e.g. prefabaanbouw). Required when multiple profiles exist. Use env-list to discover available profiles.\",\n },\n },\n required: [\"appName\", \"environment\", \"content\"],\n },\n },\n {\n name: \"cache-purge\",\n description:\n \"Purge ALL caches on a server in one operation: OPcache (kills lsphp), LiteSpeed cache, WordPress object cache (wp-cli or file-based), PrestaShop Smarty/app cache, Redis FLUSHALL, and Memcached flush. Returns a per-cache status report.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n serverId: { type: \"string\", description: \"UUID of the SSH server\" },\n },\n required: [\"serverId\"],\n },\n },\n // ----- Domains (mijn.host) -----\n {\n name: \"domain-list\",\n description:\n \"List all domains from the mijn.host account. Returns domain name, status, renewal date (= expiration), and tags. Requires MIJNHOST_API_KEY.\\n\\n\" +\n \"Pass `details: true` to also fetch DNS zone summary per domain in parallel: MX target(s) and presence of SPF/DMARC TXT records. Useful as a single-call overview instead of N follow-up dns-list calls. Skipped for inactive/expired domains.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n details: {\n type: \"boolean\",\n description:\n \"Inline DNS zone summary (NS, MX, SPF/DMARC presence) per domain. Adds N parallel API calls — use sparingly on large accounts.\",\n },\n concurrency: {\n type: \"number\",\n description:\n \"Max concurrent DNS lookups when details=true (default 8, max 20).\",\n },\n },\n required: [],\n },\n },\n {\n name: \"dns-list\",\n description:\n \"List all DNS records for a domain. Returns type (A, AAAA, CNAME, MX, TXT, etc.), name, value, and TTL for each record.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n domain: {\n type: \"string\",\n description: \"Domain name (e.g. example.com)\",\n },\n },\n required: [\"domain\"],\n },\n },\n {\n name: \"dns-record\",\n description:\n \"Mutate a single DNS record on a mijn.host domain. Pick the mutation with `action`:\\n\" +\n '- \"create\": add a new record. Required: type, name, value. Optional: ttl (default 3600).\\n' +\n '- \"update\": replace an existing record. Required: type, name, oldValue, newValue. Optional: ttl.\\n' +\n '- \"delete\": remove a record. Required: type, name, value.\\n\\n' +\n \"Always pass `dryRun: true` first when touching MX / SPF / DKIM / DMARC — returns a full before/after diff with a mail-auth warning and applies nothing. Re-run without dryRun once the diff looks correct.\\n\\n\" +\n \"Use `dns-list` to inspect the current zone first if you need to identify the right `oldValue`. Requires MIJNHOST_API_KEY.\\n\\n\" +\n \"Concurrency: calls are automatically serialized per domain (mijn.host's API does GET-then-PUT-the-whole-zone, so parallel calls would race and silently drop records). A minimum 750 ms gap is enforced between PUTs to the same zone, transient 5xx errors are retried once, and a stale-snapshot guard refuses to PUT a zone that suddenly shrunk. You can still fire calls in parallel — they just queue safely behind each other per domain.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n action: {\n type: \"string\",\n enum: [\"create\", \"update\", \"delete\"],\n description: \"Which mutation to perform.\",\n },\n domain: {\n type: \"string\",\n description: \"Domain name (e.g. example.com)\",\n },\n type: {\n type: \"string\",\n description:\n \"Record type: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, or TLSA\",\n },\n name: {\n type: \"string\",\n description: \"Record name (e.g. @ or subdomain).\",\n },\n value: {\n type: \"string\",\n description:\n \"Record value. Required for create + delete. Use newValue for update.\",\n },\n oldValue: {\n type: \"string\",\n description:\n \"Current value of the record (update only) — used to identify which record to replace.\",\n },\n newValue: {\n type: \"string\",\n description: \"New value for the record (update only).\",\n },\n ttl: {\n type: \"number\",\n description:\n \"TTL in seconds (min 60). Default 3600 for create; defaults to existing TTL for update.\",\n },\n dryRun: {\n type: \"boolean\",\n description:\n \"Preview the change (returns proposed diff) without applying. Recommended for MX/SPF/DKIM/DMARC.\",\n },\n },\n required: [\"action\", \"domain\", \"type\", \"name\"],\n },\n },\n // ----- Trigger.dev -----\n ...TRIGGER_TOOLS,\n // ----- Repo reference -----\n ...REPO_TOOLS,\n];\n\n// ---------------------------------------------------------------------------\n// MCP Server\n// ---------------------------------------------------------------------------\n\nconst MCP_VERSION = \"6.6.0\";\n\nasync function handleListTools() {\n if (!authContext) return { tools: TOOLS };\n\n const accessible = TOOLS.filter((tool) => {\n const requiredModule = TOOL_MODULE_MAP[tool.name];\n if (!requiredModule) return true;\n return authContext!.permissions.modules[requiredModule] === true;\n });\n\n return { tools: accessible };\n}\n\nasync function handleCallTool(request: {\n params: { name: string; arguments?: Record<string, unknown> };\n}) {\n if (!authContext) {\n return { content: [{ type: \"text\", text: \"Error: not authenticated\" }] };\n }\n\n const { name, arguments: toolArgs } = request.params;\n const a = (toolArgs || {}) as Record<string, unknown>;\n\n // Module-level permission check\n const requiredModule = TOOL_MODULE_MAP[name];\n if (\n requiredModule &&\n authContext.permissions.modules[requiredModule] !== true\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: `Access denied: you do not have permission for the \"${requiredModule}\" module (tool: ${name})`,\n },\n ],\n };\n }\n\n const startTime = Date.now();\n const serverId = (a.serverId || a.server_id) as string | undefined;\n const serverIds = a.serverIds;\n\n // Cache lookup. Hit returns immediately with the same payload (we still\n // re-postprocess so the footer reflects the original-but-cached cost).\n const cached = getCachedTool(name, a);\n let cameFromCache = false;\n let result: { content: { type: string; text: string }[] };\n if (cached) {\n result = cached;\n cameFromCache = true;\n } else {\n result = await executeToolCall(name, a, serverId);\n }\n\n const durationMs = Date.now() - startTime;\n const isError = result.content?.[0]?.text?.startsWith(\"Error:\");\n\n // Cache successful results only — never an Error: payload.\n if (!cameFromCache && !isError) {\n setCachedTool(name, a, result);\n }\n\n void writeAuditLog({\n toolName: name,\n arguments: a,\n serverId,\n resultStatus: isError ? \"error\" : \"success\",\n errorMessage: isError ? result.content?.[0]?.text : undefined,\n durationMs,\n });\n\n // Universal post-processing: truncate huge outputs + append cost footer.\n // Run *after* audit so the footer doesn't leak into log fields.\n const serverIdLabel = await resolveServerLabel(serverId, serverIds);\n return postprocessResult(result, {\n startedAtMs: startTime,\n serverIdLabel,\n toolName: name,\n args: a,\n cached: cameFromCache,\n });\n}\n\nasync function executeToolCall(\n name: string,\n a: Record<string, unknown>,\n _serverId: string | undefined,\n): Promise<{ content: { type: string; text: string }[] }> {\n const ctx = authContext!;\n\n try {\n switch (name) {\n // ----- Servers -----\n case \"list-servers\": {\n const data =\n ctx.allowedServerIds !== null\n ? await db.execute<SshServerListRow>(sql`\n SELECT\n id,\n name,\n hostname,\n port,\n username,\n tags,\n provider AS hosted_by,\n os AS os_type,\n created_at\n FROM managed_server\n WHERE id = ANY(${uuidArrayParam(ctx.allowedServerIds)})\n ORDER BY name\n `)\n : await db.execute<SshServerListRow>(sql`\n SELECT\n id,\n name,\n hostname,\n port,\n username,\n tags,\n provider AS hosted_by,\n os AS os_type,\n created_at\n FROM managed_server\n ORDER BY name\n `);\n\n const includeStats = a.includeStats === true;\n const servers = data;\n\n // Populate the running cache so fuzzy \"did you mean?\" hints work and\n // so the response footer can show server names without re-querying.\n rememberServers(servers.map((s) => ({ id: s.id, name: s.name })));\n\n // Stats are opt-in because they require an SSH round-trip per server.\n // We probe in parallel with a short per-server timeout so a single\n // unreachable host can't stall the listing.\n type Stats = {\n containers?: number;\n diskFreeHuman?: string;\n uptimeHuman?: string;\n reachable: boolean;\n error?: string;\n };\n let statsByServer: Map<string, Stats> = new Map();\n if (includeStats && servers.length > 0) {\n const parallelism = Math.max(\n 1,\n Math.min(20, Number(a.statsParallelism) || 8),\n );\n const probeTimeoutMs = Math.max(\n 1000,\n Math.min(30_000, Number(a.statsTimeoutMs) || 6000),\n );\n\n // Combined one-shot probe per server. Three pipe-delimited values:\n // <containerCount>|<diskFreeHuman>|<uptimeHuman>\n // Missing tools are tolerated (returns 0/N/A).\n const linuxProbe =\n \"echo \\\"$(docker ps -q 2>/dev/null | wc -l)|$(df -h / 2>/dev/null | awk 'NR==2{print $4}')|$(uptime -p 2>/dev/null || uptime)\\\"\";\n const windowsProbe = [\n \"$ProgressPreference='SilentlyContinue';\",\n \"$c = (docker ps -q 2>$null | Measure-Object).Count;\",\n \"$d = try { '{0:N1} GB' -f ((Get-PSDrive C).Free/1GB) } catch { 'N/A' };\",\n \"$u = try { (Get-Uptime).ToString() } catch { ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).ToString() };\",\n 'Write-Output \"$c|$d|$u\"',\n ].join(\" \");\n\n const probeOne = async (\n s: (typeof servers)[number],\n ): Promise<[string, Stats]> => {\n try {\n const { conn, proxy, os } = await getServerConnection(s.id);\n conn.timeout = probeTimeoutMs;\n const wrapped =\n os === \"windows\"\n ? buildPowerShellEncodedCommand(windowsProbe, [])\n : `bash -c ${posixQuote(linuxProbe)}`;\n const result = await sshExec(conn, wrapped, proxy);\n if (result.exitCode !== 0) {\n return [\n s.id,\n {\n reachable: false,\n error: (result.stderr || result.stdout || \"probe failed\")\n .trim()\n .slice(0, 120),\n },\n ];\n }\n const parts = result.stdout.trim().split(\"|\");\n return [\n s.id,\n {\n reachable: true,\n containers: Number(parts[0]) || 0,\n diskFreeHuman: (parts[1] || \"\").trim() || \"N/A\",\n uptimeHuman: (parts[2] || \"\").trim() || \"N/A\",\n },\n ];\n } catch (err) {\n return [\n s.id,\n {\n reachable: false,\n error:\n err instanceof Error\n ? err.message.slice(0, 120)\n : String(err).slice(0, 120),\n },\n ];\n }\n };\n\n // Bounded parallelism so we don't open 50 SSH sessions at once.\n const results: Array<[string, Stats]> = [];\n for (let i = 0; i < servers.length; i += parallelism) {\n const batch = servers.slice(i, i + parallelism);\n const chunk = await Promise.all(batch.map(probeOne));\n results.push(...chunk);\n }\n statsByServer = new Map(results);\n }\n\n const lines = servers.map((s) => {\n const tags = Array.isArray(s.tags)\n ? (s.tags as string[]).join(\", \")\n : \"\";\n const os = (s as Record<string, unknown>).os_type || \"linux\";\n const base = `${s.id} ${s.name} ${s.hostname}:${s.port} ${s.username} [${tags}] ${s.hosted_by || \"\"} os:${os}`;\n if (!includeStats) return base;\n const st = statsByServer.get(s.id);\n if (!st) return `${base} stats:skipped`;\n if (!st.reachable)\n return `${base} UNREACHABLE (${st.error || \"unknown\"})`;\n return `${base} containers:${st.containers} disk_free:${st.diskFreeHuman} uptime:${st.uptimeHuman}`;\n });\n\n // Auto-context: short hints about well-known servers, derived from\n // tags + hostnames so the LLM knows e.g. which host runs Trigger.\n const contextHints =\n a.context !== false\n ? buildServerContextHints(\n servers as Array<{\n name: string;\n hostname: string;\n tags?: string[] | null;\n }>,\n )\n : [];\n const out = lines.length ? lines.join(\"\\n\") : \"No servers found\";\n return {\n content: [\n {\n type: \"text\",\n text: contextHints.length\n ? `${out}\\n\\n--- context ---\\n${contextHints.join(\"\\n\")}`\n : out,\n },\n ],\n };\n }\n\n // ----- SSH -----\n case \"ssh-execute\": {\n // Parse modes: pipeline (multi-cmd one session), repeat (loop), format (parser).\n const pipeline: string[] = Array.isArray(a.pipeline)\n ? (a.pipeline as unknown[]).map(String).filter(Boolean)\n : [];\n const command = pipeline.length > 0 ? \"\" : String(a.command || \"\");\n if (!command && pipeline.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: pass either `command` or `pipeline[]`\",\n },\n ],\n };\n }\n if (command) assertSafeCommand(command);\n for (const c of pipeline) assertSafeCommand(c);\n\n const args = Array.isArray(a.args)\n ? (a.args as unknown[]).map(String)\n : undefined;\n const stdin = typeof a.stdin === \"string\" ? a.stdin : undefined;\n const shellOverride =\n typeof a.shell === \"string\"\n ? (a.shell as \"auto\" | \"bash\" | \"powershell\")\n : \"auto\";\n const cwd = typeof a.cwd === \"string\" && a.cwd ? a.cwd : undefined;\n const timeoutMs = a.timeout ? Number(a.timeout) : undefined;\n // Idle timeout default 120s — covers 99% of \"is this hung?\" cases\n // without forcing the LLM to think about wall budgets. Pass 0 to disable.\n const rawIdle =\n a.idleTimeoutSeconds !== undefined\n ? Number(a.idleTimeoutSeconds)\n : 120;\n const idleTimeoutMs =\n Number.isFinite(rawIdle) && rawIdle > 0 ? rawIdle * 1000 : undefined;\n // Repeat / diff / format are post-processing modes layered on top of\n // the single-shot or pipeline run. Repeat returns combined timing data.\n const repeat = Math.max(1, Math.min(60, Number(a.repeat) || 1));\n const intervalSeconds = Math.max(\n 0,\n Math.min(600, Number(a.intervalSeconds) || 0),\n );\n const repeatOutput =\n a.output === \"diff\" || a.output === \"last\" ? a.output : \"all\";\n const format = a.format === \"ndjson\" ? \"ndjson\" : \"text\";\n // Pipeline error policy: stop-on-first-fail vs continue (default continue\n // so all outputs reach the LLM in one round-trip).\n const pipelineStopOnError = a.pipelineStopOnError === true;\n\n // Resolve target list. `serverIds` (array) wins over `serverId` (single).\n // Both forms are supported so the existing `serverId` API stays intact.\n const targetIds: string[] =\n Array.isArray(a.serverIds) && a.serverIds.length > 0\n ? (a.serverIds as unknown[]).map(String)\n : a.serverId\n ? [String(a.serverId)]\n : [];\n if (targetIds.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: pass either `serverId` or `serverIds[]`\",\n },\n ],\n };\n }\n\n const parallelism = Math.max(\n 1,\n Math.min(20, Number(a.parallelism) || 5),\n );\n\n // Per-server runner. Resolves connection, builds OS-aware command, runs.\n // Returns the final SshResult; pipeline parsing happens after the call.\n const runOne = async (\n serverId: string,\n ): Promise<{\n serverId: string;\n serverName: string;\n os: ServerOs;\n shell: \"bash\" | \"powershell\";\n result: SshResult;\n pipelineSegments?: PipelineSegment[];\n iterations?: IterationResult[];\n }> => {\n const { conn, proxy, os } = await getServerConnection(serverId);\n if (timeoutMs) conn.timeout = timeoutMs;\n const shell =\n shellOverride === \"auto\"\n ? os === \"windows\"\n ? \"powershell\"\n : \"bash\"\n : shellOverride;\n\n // Build the body (single command OR pipeline wrapper). Pipeline mode\n // overrides any args/cwd-on-command behavior — cwd applies to the\n // whole script wrapper instead.\n let body: string;\n let pipelineMarker: string | null = null;\n if (pipeline.length > 0) {\n pipelineMarker = `__MCP_BREAK_${randomBytes(8).toString(\"hex\")}__`;\n body = buildPipelineScript(\n pipeline,\n shell,\n pipelineMarker,\n pipelineStopOnError,\n );\n } else if (args && args.length > 0) {\n body =\n shell === \"powershell\"\n ? buildPowerShellEncodedCommand(command, args)\n : buildPosixCommand(command, args);\n } else if (\n shell === \"powershell\" &&\n !/^powershell\\b/i.test(command.trim())\n ) {\n // For Windows raw strings, still wrap so $/quotes don't get reinterpreted.\n body = buildPowerShellEncodedCommand(command, []);\n } else {\n body = command;\n }\n\n // Apply cwd. For PowerShell with EncodedCommand, we can't simply\n // prepend `cd ... && ...` because `body` is already a full\n // `powershell -EncodedCommand <b64>` invocation. Instead we re-encode\n // a wrapper script that does `Set-Location` then runs the original.\n const applyCwd = (rawBody: string): string => {\n if (!cwd) return rawBody;\n if (shell === \"bash\") return `cd ${posixQuote(cwd)} && ${rawBody}`;\n const ecMatch = rawBody.match(/-EncodedCommand\\s+(\\S+)$/);\n if (!ecMatch) return rawBody;\n const decoded = Buffer.from(\n ecMatch[1] as string,\n \"base64\",\n ).toString(\"utf16le\");\n const wrapped = `Set-Location -LiteralPath '${cwd.replace(/'/g, \"''\")}'; ${decoded}`;\n const reencoded = Buffer.from(wrapped, \"utf16le\").toString(\n \"base64\",\n );\n return rawBody.replace(\n /-EncodedCommand\\s+\\S+$/,\n `-EncodedCommand ${reencoded}`,\n );\n };\n const finalCmd = applyCwd(body);\n\n // Repeat mode: run finalCmd N times with optional sleep between.\n // We never sleep server-side; we sleep here so each iteration gets\n // its own SSH session and clean idle timer.\n if (repeat > 1) {\n const iterations: IterationResult[] = [];\n for (let i = 0; i < repeat; i++) {\n const startedAt = Date.now();\n const r = await sshExec(conn, finalCmd, proxy, {\n ...(stdin !== undefined ? { stdin } : {}),\n idleTimeoutMs,\n });\n iterations.push({\n index: i,\n startedAt,\n durationMs: Date.now() - startedAt,\n result: r,\n });\n if (i < repeat - 1 && intervalSeconds > 0) {\n await new Promise((res) =>\n setTimeout(res, intervalSeconds * 1000),\n );\n }\n }\n const last = iterations[iterations.length - 1]!.result;\n let serverName = serverId;\n try {\n const nameRows = await db.execute<SshServerNameRow>(\n sql`SELECT name FROM managed_server WHERE id = ${serverId} LIMIT 1`,\n );\n if (nameRows[0]?.name) serverName = nameRows[0].name;\n } catch {\n /* fall back to id */\n }\n return {\n serverId,\n serverName,\n os,\n shell,\n result: last,\n iterations,\n };\n }\n\n const result = await sshExec(conn, finalCmd, proxy, {\n ...(stdin !== undefined ? { stdin } : {}),\n idleTimeoutMs,\n });\n let pipelineSegments: PipelineSegment[] | undefined;\n if (pipelineMarker && pipeline.length > 0) {\n pipelineSegments = parsePipelineOutput(\n result.stdout,\n pipeline,\n pipelineMarker,\n );\n }\n let serverName = serverId;\n try {\n const nameRows = await db.execute<SshServerNameRow>(\n sql`SELECT name FROM managed_server WHERE id = ${serverId} LIMIT 1`,\n );\n if (nameRows[0]?.name) serverName = nameRows[0].name;\n } catch {\n /* fall back to id */\n }\n return { serverId, serverName, os, shell, result, pipelineSegments };\n };\n\n // Render helper for a single per-server result (pipeline/repeat aware).\n const renderOne = (r: Awaited<ReturnType<typeof runOne>>): string => {\n if (r.iterations && r.iterations.length > 0) {\n return renderRepeatResult(r.iterations, repeatOutput, format);\n }\n if (r.pipelineSegments) {\n return renderPipelineSegments(r.pipelineSegments, r.result, format);\n }\n const output = [\n `Exit code: ${r.result.exitCode} (os: ${r.os}, shell: ${r.shell})`,\n ];\n let stdoutText = r.result.stdout;\n if (format === \"ndjson\" && stdoutText) {\n const parsed = tryParseNdjsonFromCommand(command, stdoutText);\n if (parsed) stdoutText = parsed;\n }\n if (stdoutText) output.push(`--- stdout ---\\n${stdoutText}`);\n if (r.result.stderr)\n output.push(`--- stderr ---\\n${r.result.stderr}`);\n return output.join(\"\\n\");\n };\n\n // Single-target: keep the original output format unchanged.\n if (targetIds.length === 1) {\n const r = await runOne(targetIds[0] as string);\n return { content: [{ type: \"text\", text: renderOne(r) }] };\n }\n\n // Fan-out: bounded parallel execution. We run in batches of `parallelism`.\n const allResults: Array<\n | Awaited<ReturnType<typeof runOne>>\n | { serverId: string; error: string }\n > = [];\n for (let i = 0; i < targetIds.length; i += parallelism) {\n const batch = targetIds.slice(i, i + parallelism);\n const settled = await Promise.allSettled(\n batch.map((id) => runOne(id)),\n );\n for (let j = 0; j < settled.length; j++) {\n const s = settled[j]!;\n if (s.status === \"fulfilled\") allResults.push(s.value);\n else\n allResults.push({\n serverId: batch[j] as string,\n error:\n s.reason instanceof Error\n ? s.reason.message\n : String(s.reason),\n });\n }\n }\n\n // Render per-server sections + a 1-line summary at the bottom.\n const sections: string[] = [];\n let okCount = 0;\n let failCount = 0;\n for (const r of allResults) {\n if (\"error\" in r) {\n failCount++;\n sections.push(\n `=== ${r.serverId} === !! connection error: ${r.error}`,\n );\n continue;\n }\n if (r.result.exitCode === 0) okCount++;\n else failCount++;\n const header = `=== ${r.serverName} (${r.os}, exit ${r.result.exitCode}) ===`;\n sections.push(`${header}\\n${renderOne(r)}`);\n }\n sections.push(\n `--- fan-out summary: ${okCount} ok / ${failCount} failed across ${allResults.length} servers (parallelism ${parallelism}) ---`,\n );\n return { content: [{ type: \"text\", text: sections.join(\"\\n\\n\") }] };\n }\n\n // ----- SFTP -----\n case \"sftp-list\": {\n const bucket = typeof a.bucket === \"string\" && a.bucket ? a.bucket : \"\";\n const recursive = a.recursive === true;\n const maxResults = Math.max(\n 1,\n Math.min(50_000, Number(a.maxResults) || 5_000),\n );\n const pattern = typeof a.pattern === \"string\" ? a.pattern : \"\";\n const summary = a.summary === true;\n // Sort key: 'name' (default), 'size', 'mtime'. `reverse: true` flips.\n const sortBy =\n a.sortBy === \"size\" || a.sortBy === \"mtime\" || a.sortBy === \"name\"\n ? a.sortBy\n : \"name\";\n const reverse = a.reverse === true;\n\n // Collect into a backend-agnostic shape so sort/reverse/summary apply\n // identically to SSH and R2 listings.\n let entries: SftpEntry[];\n let truncated = false;\n let warning = \"\";\n\n if (bucket) {\n const prefix = r2Key(String(a.path || \"\"));\n const matcher = pattern ? globToRegExp(pattern) : null;\n const r2Entries = await r2List(bucket, prefix, {\n recursive,\n maxResults,\n });\n const filtered = matcher\n ? r2Entries.filter((e) =>\n matcher.test(e.key.split(\"/\").pop() || e.key),\n )\n : r2Entries;\n entries = filtered.map((e) => {\n const ms = e.mtime ? Date.parse(e.mtime) : 0;\n return {\n kind: e.isPrefix ? (\"d\" as const) : (\"-\" as const),\n size: e.size,\n mtime: e.mtime,\n mtimeMs: Number.isFinite(ms) ? ms : 0,\n path: e.key,\n };\n });\n } else {\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n const result = await sftpReaddir(conn, String(a.path || \"/\"), proxy, {\n recursive,\n maxDepth: typeof a.maxDepth === \"number\" ? a.maxDepth : undefined,\n pattern: pattern || undefined,\n maxResults,\n });\n if (result.error && result.entries.length === 0) {\n return {\n content: [{ type: \"text\", text: `Error: ${result.error}` }],\n };\n }\n entries = result.entries;\n truncated = result.truncated;\n if (result.error) warning = result.error;\n }\n\n // Summary mode short-circuits before sorting (we just aggregate).\n if (summary) {\n const files = entries.filter((e) => e.kind === \"-\");\n const dirs = entries.filter((e) => e.kind === \"d\");\n const totalSize = files.reduce((acc, e) => acc + (e.size || 0), 0);\n const lines = [\n `Files: ${files.length}`,\n `Directories: ${dirs.length}`,\n `Total size: ${totalSize} bytes (${(totalSize / (1024 * 1024)).toFixed(2)} MB)`,\n ];\n if (truncated)\n lines.push(`(truncated at ${maxResults}; counts may be partial)`);\n if (warning) lines.push(`(warnings: ${warning})`);\n return { content: [{ type: \"text\", text: lines.join(\"\\n\") }] };\n }\n\n // Sort. Directories first within the chosen sort, both ascending by\n // default; `reverse: true` flips the secondary order. `name` uses\n // localeCompare so digits/dots sort naturally.\n entries.sort((x, y) => {\n if (x.kind !== y.kind) return x.kind === \"d\" ? -1 : 1;\n let cmp = 0;\n if (sortBy === \"size\") cmp = x.size - y.size;\n else if (sortBy === \"mtime\") cmp = x.mtimeMs - y.mtimeMs;\n else cmp = x.path.localeCompare(y.path);\n return reverse ? -cmp : cmp;\n });\n\n if (entries.length === 0)\n return { content: [{ type: \"text\", text: \"No entries\" }] };\n const lines = entries.map((e) => {\n const sizeCol =\n e.kind === \"d\" && bucket ? \"(prefix)\" : String(e.size);\n return `${e.kind} ${sizeCol.padStart(10)} ${(e.mtime || \"\").padEnd(24)} ${e.path}`;\n });\n if (truncated)\n lines.push(\n `... (truncated at ${maxResults} entries; raise maxResults or narrow path/pattern)`,\n );\n if (warning) lines.push(`! ${warning}`);\n return { content: [{ type: \"text\", text: lines.join(\"\\n\") }] };\n }\n\n case \"sftp-read\": {\n const bucket = typeof a.bucket === \"string\" && a.bucket ? a.bucket : \"\";\n const offset =\n a.offset !== undefined ? Math.max(0, Number(a.offset)) : undefined;\n const length =\n a.length !== undefined ? Math.max(0, Number(a.length)) : undefined;\n const hasRange = offset !== undefined || length !== undefined;\n\n if (bucket) {\n const key = r2Key(String(a.path));\n if (!key)\n return {\n content: [{ type: \"text\", text: \"Error: path is required\" }],\n };\n try {\n if (hasRange) {\n const content = await r2GetObjectRange(bucket, key, {\n offset: offset ?? 0,\n length,\n });\n return { content: [{ type: \"text\", text: content }] };\n }\n const content = await r2GetObject(bucket, key, 1_048_576);\n return { content: [{ type: \"text\", text: content }] };\n } catch (e) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n };\n }\n }\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n const content = await sftpRead(\n conn,\n String(a.path),\n proxy,\n hasRange ? { offset, length } : undefined,\n );\n return { content: [{ type: \"text\", text: content }] };\n }\n\n case \"sftp-write\": {\n const bucket = typeof a.bucket === \"string\" && a.bucket ? a.bucket : \"\";\n\n // Cross-endpoint copy mode. Activates when `sourceRemote` is set:\n // sourceRemote: { serverId|bucket, path }\n // target endpoint: top-level { serverId|bucket, path } (the existing\n // sftp-write target shape — no schema change for the LLM).\n // Supported directions: ssh↔ssh, ssh↔r2, r2↔ssh, r2↔r2 (server-side).\n if (a.sourceRemote && typeof a.sourceRemote === \"object\") {\n const srcRaw = a.sourceRemote as Record<string, unknown>;\n const srcBucket =\n typeof srcRaw.bucket === \"string\" && srcRaw.bucket\n ? String(srcRaw.bucket)\n : \"\";\n const srcServerId =\n typeof srcRaw.serverId === \"string\" && srcRaw.serverId\n ? String(srcRaw.serverId)\n : \"\";\n const srcPath = String(srcRaw.path || \"\");\n if (!srcPath)\n return {\n content: [\n { type: \"text\", text: \"Error: sourceRemote.path is required\" },\n ],\n };\n if (!srcBucket && !srcServerId)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: sourceRemote needs `serverId` or `bucket`\",\n },\n ],\n };\n if (srcBucket && srcServerId)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: sourceRemote can have either `serverId` or `bucket`, not both\",\n },\n ],\n };\n\n const dstPath = String(a.path || \"\");\n if (!dstPath)\n return {\n content: [\n { type: \"text\", text: \"Error: target `path` is required\" },\n ],\n };\n\n let srcEp: CopyEndpoint;\n if (srcBucket) {\n const k = r2Key(srcPath);\n if (!k)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: sourceRemote.path resolves to empty key\",\n },\n ],\n };\n srcEp = { kind: \"r2\", bucket: srcBucket, key: k };\n } else {\n const { conn, proxy } = await getServerConnection(srcServerId);\n srcEp = { kind: \"ssh\", opts: conn, proxy, path: srcPath };\n }\n\n let dstEp: CopyEndpoint;\n if (bucket) {\n const k = r2Key(dstPath);\n if (!k)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: target path resolves to empty key\",\n },\n ],\n };\n dstEp = { kind: \"r2\", bucket, key: k };\n } else if (a.serverId) {\n const { conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n dstEp = { kind: \"ssh\", opts: conn, proxy, path: dstPath };\n } else {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: target needs `serverId` or `bucket`\",\n },\n ],\n };\n }\n\n try {\n const { bytes, elapsedMs, mode } = await sftpCopy(srcEp, dstEp);\n const srcLabel =\n srcEp.kind === \"r2\"\n ? `r2://${srcEp.bucket}/${srcEp.key}`\n : `ssh:${srcPath}`;\n const dstLabel =\n dstEp.kind === \"r2\"\n ? `r2://${dstEp.bucket}/${dstEp.key}`\n : `ssh:${dstPath}`;\n const mbps =\n bytes > 0 && elapsedMs > 0\n ? bytes / (1024 * 1024) / (elapsedMs / 1000)\n : 0;\n return {\n content: [\n {\n type: \"text\",\n text: `Copied ${formatBytes(bytes)} from ${srcLabel} → ${dstLabel} via ${mode} in ${(elapsedMs / 1000).toFixed(2)}s${mbps > 0 ? ` (${mbps.toFixed(1)} MB/s)` : \"\"}`,\n },\n ],\n };\n } catch (e) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n };\n }\n }\n\n // Optional file metadata. `mode` accepts a number (0o755) or a string\n // (\"755\" or \"0o755\") so the LLM can write either form. mtime accepts\n // ms since epoch or an ISO date string.\n let fileMode: number | undefined;\n if (typeof a.mode === \"number\" && Number.isFinite(a.mode))\n fileMode = a.mode & 0o7777;\n else if (typeof a.mode === \"string\" && a.mode) {\n const cleaned = a.mode.replace(/^0o?/i, \"\");\n const parsed = Number.parseInt(cleaned, 8);\n if (!Number.isNaN(parsed)) fileMode = parsed & 0o7777;\n }\n let mtimeMs: number | undefined;\n if (typeof a.mtime === \"number\" && Number.isFinite(a.mtime))\n mtimeMs = a.mtime;\n else if (typeof a.mtime === \"string\" && a.mtime) {\n const parsed = Date.parse(a.mtime);\n if (!Number.isNaN(parsed)) mtimeMs = parsed;\n }\n\n if (bucket) {\n const key = r2Key(String(a.path));\n if (!key)\n return {\n content: [{ type: \"text\", text: \"Error: path is required\" }],\n };\n if (fileMode !== undefined || mtimeMs !== undefined) {\n // R2 (S3) has no POSIX mode/mtime. Surface this so the user knows\n // the params were ignored rather than silently dropping them.\n // We continue with the upload anyway.\n }\n try {\n if (typeof a.sourcePath === \"string\" && a.sourcePath.length > 0) {\n const local = a.sourcePath;\n if (!isAbsolute(local))\n return {\n content: [\n {\n type: \"text\",\n text: `Error: sourcePath must be an absolute path: ${local}`,\n },\n ],\n };\n if (!existsSync(local))\n return {\n content: [\n {\n type: \"text\",\n text: `Error: sourcePath does not exist: ${local}`,\n },\n ],\n };\n const st = statSync(local);\n if (!st.isFile())\n return {\n content: [\n {\n type: \"text\",\n text: `Error: sourcePath is not a regular file: ${local}`,\n },\n ],\n };\n const startedAt = Date.now();\n if (st.size > R2_MULTIPART_THRESHOLD) {\n // Multipart path: streams the local file in 100 MB parts and\n // logs progress per part. Up to ~5 TB per object on R2.\n let lastLog = 0;\n await r2PutObjectMultipart(\n bucket,\n key,\n local,\n st.size,\n (uploaded) => {\n if (uploaded - lastLog >= 500 * 1024 * 1024) {\n console.error(\n `[r2-write] ${formatBytes(uploaded)} / ${formatBytes(st.size)} → r2://${bucket}/${key}`,\n );\n lastLog = uploaded;\n }\n },\n );\n const elapsed = Date.now() - startedAt;\n const mbps =\n st.size / (1024 * 1024) / Math.max(0.001, elapsed / 1000);\n const noteParts: string[] = [];\n if (fileMode !== undefined) noteParts.push(\"mode ignored (R2)\");\n if (mtimeMs !== undefined) noteParts.push(\"mtime ignored (R2)\");\n const note = noteParts.length\n ? ` [${noteParts.join(\", \")}]`\n : \"\";\n return {\n content: [\n {\n type: \"text\",\n text: `Uploaded ${formatBytes(st.size)} from ${local} to r2://${bucket}/${key} via multipart in ${(elapsed / 1000).toFixed(1)}s (${mbps.toFixed(1)} MB/s)${note}`,\n },\n ],\n };\n }\n const stream = createReadStream(local);\n await r2PutObject(bucket, key, stream, st.size);\n const elapsed = Date.now() - startedAt;\n return {\n content: [\n {\n type: \"text\",\n text: `Uploaded ${st.size} bytes from ${local} to r2://${bucket}/${key} in ${elapsed}ms`,\n },\n ],\n };\n }\n const buf = Buffer.from(String(a.content ?? \"\"), \"utf-8\");\n await r2PutObject(bucket, key, buf, buf.length);\n return {\n content: [\n {\n type: \"text\",\n text: `Wrote ${buf.length} bytes to r2://${bucket}/${key}`,\n },\n ],\n };\n } catch (e) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n };\n }\n }\n\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n const input: SftpWriteInput =\n typeof a.sourcePath === \"string\" && a.sourcePath.length > 0\n ? { sourcePath: a.sourcePath }\n : { content: String(a.content ?? \"\") };\n const result = await sftpWrite(conn, String(a.path), input, proxy, {\n fileMode,\n mtimeMs,\n });\n return { content: [{ type: \"text\", text: result }] };\n }\n\n case \"sftp-delete\": {\n const bucket = typeof a.bucket === \"string\" && a.bucket ? a.bucket : \"\";\n const recursive = a.recursive === true;\n const dryRun = a.dryRun === true;\n const confirmAbove =\n a.confirmAbove !== undefined\n ? Math.max(0, Number(a.confirmAbove))\n : undefined;\n const confirmCount =\n a.confirmCount !== undefined ? Number(a.confirmCount) : undefined;\n\n // Helper: enforce confirmAbove gate on a known item count (or refuse).\n const guard = (\n count: number,\n sizeBytes: number,\n where: string,\n ): { content: [{ type: \"text\"; text: string }] } | null => {\n if (confirmAbove !== undefined && count > confirmAbove) {\n if (confirmCount === count) return null; // user explicitly opted in\n return {\n content: [\n {\n type: \"text\",\n text: `Refusing to delete ${count} item(s) (${formatBytes(sizeBytes)}) under ${where}: exceeds confirmAbove=${confirmAbove}. To proceed, re-issue the call with confirmCount: ${count}.`,\n },\n ],\n };\n }\n return null;\n };\n\n if (bucket) {\n const key = r2Key(String(a.path));\n if (!key)\n return {\n content: [{ type: \"text\", text: \"Error: path is required\" }],\n };\n try {\n if (recursive) {\n // For recursive R2 we need to list first to count + size, both\n // for the dryRun preview and for the confirmAbove gate.\n if (dryRun || confirmAbove !== undefined) {\n const listed = await r2List(bucket, key, {\n recursive: true,\n maxResults: 50_000,\n });\n const objects = listed.filter((e) => !e.isPrefix);\n const totalSize = objects.reduce(\n (s, o) => s + (o.size || 0),\n 0,\n );\n if (dryRun) {\n const sample = objects\n .slice(0, 5)\n .map(\n (o) =>\n ` - r2://${bucket}/${o.key} (${formatBytes(o.size || 0)})`,\n );\n return {\n content: [\n {\n type: \"text\",\n text: `[dry-run] Would delete ${objects.length} object(s) totalling ${formatBytes(totalSize)} under r2://${bucket}/${key}${objects.length > 5 ? `\\n${sample.join(\"\\n\")}\\n ... and ${objects.length - 5} more` : objects.length ? `\\n${sample.join(\"\\n\")}` : \"\"}`,\n },\n ],\n };\n }\n const block = guard(\n objects.length,\n totalSize,\n `r2://${bucket}/${key}`,\n );\n if (block) return block;\n }\n const deleted = await r2DeletePrefix(bucket, key);\n return {\n content: [\n {\n type: \"text\",\n text: `Deleted ${deleted} object(s) under r2://${bucket}/${key}`,\n },\n ],\n };\n }\n // Single-object delete: dryRun shows size; no confirmAbove gate needed.\n if (dryRun) {\n try {\n const head = await getR2Client().send(\n new HeadObjectCommand({ Bucket: bucket, Key: key }),\n );\n return {\n content: [\n {\n type: \"text\",\n text: `[dry-run] Would delete r2://${bucket}/${key} (${formatBytes(head.ContentLength || 0)})`,\n },\n ],\n };\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `[dry-run] r2://${bucket}/${key} not found (delete would 404)`,\n },\n ],\n };\n }\n }\n await r2DeleteObject(bucket, key);\n return {\n content: [\n { type: \"text\", text: `Deleted r2://${bucket}/${key}` },\n ],\n };\n } catch (e) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n };\n }\n }\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n\n // SSH path: dryRun + confirmAbove for recursive — we list first so the\n // preview/gate has the same data the actual delete would.\n if (recursive && (dryRun || confirmAbove !== undefined)) {\n const listed = await sftpReaddir(conn, String(a.path), proxy, {\n recursive: true,\n maxResults: 50_000,\n });\n const files = listed.entries.filter((e) => e.kind === \"-\");\n const dirs = listed.entries.filter((e) => e.kind === \"d\");\n const totalSize = files.reduce((s, f) => s + (f.size || 0), 0);\n if (dryRun) {\n const sample = files\n .slice(0, 5)\n .map((f) => ` - ${f.path} (${formatBytes(f.size || 0)})`);\n return {\n content: [\n {\n type: \"text\",\n text: `[dry-run] Would delete ${files.length} file(s) + ${dirs.length} directory(ies) totalling ${formatBytes(totalSize)} under ${a.path}${files.length ? `\\n${sample.join(\"\\n\")}${files.length > 5 ? `\\n ... and ${files.length - 5} more` : \"\"}` : \"\"}`,\n },\n ],\n };\n }\n const block = guard(\n files.length + dirs.length,\n totalSize,\n String(a.path),\n );\n if (block) return block;\n } else if (dryRun) {\n // Single-file dry-run: just print intent. Avoids an extra round-trip\n // and works equally well for files that don't exist (the real delete\n // would surface that anyway).\n return {\n content: [\n {\n type: \"text\",\n text: `[dry-run] Would delete ${a.path} (single file/dir; pass recursive: true to preview tree contents)`,\n },\n ],\n };\n }\n const result = await sftpDelete(conn, String(a.path), proxy, {\n recursive,\n });\n return { content: [{ type: \"text\", text: result }] };\n }\n\n // ----- Docker -----\n case \"docker-list\": {\n const format = a.format === \"json\" ? \"json\" : \"table\";\n const composeOnly = a.composeOnly === true;\n const groupByProject = a.groupByProject === true;\n const nameFiltersRaw: string[] = Array.isArray(a.nameFilter)\n ? (a.nameFilter as unknown[])\n .map((v) => String(v).trim())\n .filter(Boolean)\n : typeof a.nameFilter === \"string\" && a.nameFilter.trim()\n ? [a.nameFilter.trim()]\n : [];\n\n // Resolve target list — same fan-out idiom as ssh-execute.\n const targetIds: string[] =\n Array.isArray(a.serverIds) && a.serverIds.length > 0\n ? (a.serverIds as unknown[]).map(String)\n : a.serverId\n ? [String(a.serverId)]\n : [];\n if (targetIds.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: pass either `serverId` or `serverIds[]`\",\n },\n ],\n };\n }\n const parallelism = Math.max(\n 1,\n Math.min(20, Number(a.parallelism) || 5),\n );\n\n type DockerPsRow = {\n Names?: string;\n Image?: string;\n Status?: string;\n Ports?: string;\n Labels?: string;\n Project?: string;\n Health?: string;\n };\n\n const filterArg = composeOnly\n ? ` --filter \"label=com.docker.compose.project\"`\n : \"\";\n const cmd = `docker ps -a${filterArg} --format '{{json .}}'`;\n\n const probeOne = async (\n serverId: string,\n ): Promise<{\n serverId: string;\n serverName: string;\n rows: DockerPsRow[];\n error?: string;\n }> => {\n let serverName = serverId.slice(0, 8);\n try {\n const { conn, proxy } = await getServerConnection(serverId);\n const r = await sshExec(conn, cmd, proxy);\n const cached = KNOWN_SERVER_NAMES.get(serverId);\n if (cached) serverName = cached.name;\n if (r.exitCode !== 0) {\n return {\n serverId,\n serverName,\n rows: [],\n error: (r.stderr || r.stdout || \"exit \" + r.exitCode)\n .trim()\n .slice(0, 200),\n };\n }\n const rows: DockerPsRow[] = [];\n for (const line of r.stdout.split(\"\\n\")) {\n const t = line.trim();\n if (!t) continue;\n try {\n rows.push(JSON.parse(t) as DockerPsRow);\n } catch {\n /* skip malformed */\n }\n }\n for (const c of rows) {\n const m = (c.Labels || \"\").match(\n /com\\.docker\\.compose\\.project=([^,]+)/,\n );\n c.Project = m ? m[1] : \"\";\n const status = c.Status || \"\";\n if (/\\(unhealthy\\)/i.test(status)) c.Health = \"unhealthy\";\n else if (/\\(health: starting\\)|\\(starting\\)/i.test(status))\n c.Health = \"starting\";\n else if (/\\(healthy\\)/i.test(status)) c.Health = \"healthy\";\n else if (/^Up\\b/i.test(status)) c.Health = \"no-check\";\n else c.Health = \"\";\n }\n // Stash names for fuzzy hints later.\n rememberContainers(\n serverId,\n rows.map((r) => r.Names || \"\").filter(Boolean),\n );\n return { serverId, serverName, rows };\n } catch (err) {\n return {\n serverId,\n serverName,\n rows: [],\n error:\n err instanceof Error\n ? err.message.slice(0, 200)\n : String(err).slice(0, 200),\n };\n }\n };\n\n const perServer: Awaited<ReturnType<typeof probeOne>>[] = [];\n for (let i = 0; i < targetIds.length; i += parallelism) {\n const batch = targetIds.slice(i, i + parallelism);\n const chunk = await Promise.all(batch.map(probeOne));\n perServer.push(...chunk);\n }\n\n // Per-row apply name filter, tagging origin server when fan-out > 1.\n const applyFilter = (rows: DockerPsRow[]): DockerPsRow[] => {\n if (nameFiltersRaw.length === 0) return rows;\n const matchers = nameFiltersRaw.map((raw) => {\n if (raw.includes(\"*\") || raw.includes(\"?\"))\n return { kind: \"glob\" as const, re: globToRegExp(raw) };\n return { kind: \"sub\" as const, lower: raw.toLowerCase() };\n });\n return rows.filter((c) => {\n const name = c.Names || \"\";\n const lower = name.toLowerCase();\n return matchers.some((m) =>\n m.kind === \"glob\" ? m.re.test(name) : lower.includes(m.lower),\n );\n });\n };\n const sortRows = (rows: DockerPsRow[]) =>\n rows.sort((x, y) => {\n const px = x.Project || \"~\";\n const py = y.Project || \"~\";\n const p = px.localeCompare(py);\n return p !== 0 ? p : (x.Names || \"\").localeCompare(y.Names || \"\");\n });\n\n const fmtRow = (r: DockerPsRow) =>\n `${(r.Names || \"\").padEnd(36)} ${(r.Image || \"\").padEnd(40)} ${(r.Status || \"\").padEnd(24)} ${(r.Health || \"\").padEnd(10)} ${(r.Ports || \"\").padEnd(40)}`;\n\n // Single-server: keep original (terse, unprefixed) layout.\n if (targetIds.length === 1) {\n const only = perServer[0]!;\n if (only.error)\n return {\n content: [{ type: \"text\", text: `Error: ${only.error}` }],\n };\n const filtered = sortRows(applyFilter(only.rows));\n if (format === \"json\") {\n const text =\n filtered.map((c) => JSON.stringify(c)).join(\"\\n\") ||\n \"(no containers)\";\n return { content: [{ type: \"text\", text }] };\n }\n if (groupByProject) {\n const groups = new Map<string, DockerPsRow[]>();\n for (const c of filtered) {\n const key = c.Project || \"(no compose project)\";\n const list = groups.get(key);\n if (list) list.push(c);\n else groups.set(key, [c]);\n }\n const out: string[] = [];\n for (const [project, rows] of groups) {\n out.push(`=== ${project} (${rows.length}) ===`);\n for (const r of rows) out.push(\" \" + fmtRow(r));\n out.push(\"\");\n }\n return {\n content: [\n {\n type: \"text\",\n text: out.join(\"\\n\").trimEnd() || \"(no containers)\",\n },\n ],\n };\n }\n const header = `${\"NAMES\".padEnd(36)} ${\"IMAGE\".padEnd(40)} ${\"STATUS\".padEnd(24)} ${\"HEALTH\".padEnd(10)} ${\"PORTS\".padEnd(40)} PROJECT`;\n const body = filtered.map((r) => `${fmtRow(r)} ${r.Project || \"\"}`);\n const text =\n filtered.length === 0\n ? \"(no containers match)\"\n : [header, ...body].join(\"\\n\");\n return { content: [{ type: \"text\", text }] };\n }\n\n // Fan-out: per-server header, then filtered rows. JSON format produces\n // one obj per line with an extra \"Server\" field so downstream tools\n // can tell containers apart.\n if (format === \"json\") {\n const lines: string[] = [];\n for (const ps of perServer) {\n if (ps.error) {\n lines.push(\n JSON.stringify({ Server: ps.serverName, Error: ps.error }),\n );\n continue;\n }\n const filtered = sortRows(applyFilter(ps.rows));\n for (const c of filtered)\n lines.push(JSON.stringify({ Server: ps.serverName, ...c }));\n }\n return {\n content: [\n { type: \"text\", text: lines.join(\"\\n\") || \"(no containers)\" },\n ],\n };\n }\n\n const sections: string[] = [];\n let totalRows = 0;\n let serversWithRows = 0;\n for (const ps of perServer) {\n if (ps.error) {\n sections.push(`=== ${ps.serverName} === !! ${ps.error}`);\n continue;\n }\n const filtered = sortRows(applyFilter(ps.rows));\n if (filtered.length === 0) {\n sections.push(`=== ${ps.serverName} === (no containers match)`);\n continue;\n }\n serversWithRows++;\n totalRows += filtered.length;\n sections.push(\n `=== ${ps.serverName} (${filtered.length} container(s)) ===`,\n );\n const header = `${\"NAMES\".padEnd(36)} ${\"IMAGE\".padEnd(40)} ${\"STATUS\".padEnd(24)} ${\"HEALTH\".padEnd(10)} ${\"PORTS\".padEnd(40)} PROJECT`;\n sections.push(header);\n for (const r of filtered)\n sections.push(`${fmtRow(r)} ${r.Project || \"\"}`);\n }\n sections.push(\n `--- fan-out summary: ${totalRows} container(s) across ${serversWithRows}/${perServer.length} server(s) ---`,\n );\n return { content: [{ type: \"text\", text: sections.join(\"\\n\") }] };\n }\n\n case \"docker-logs\": {\n const rawNames = Array.isArray(a.containerName)\n ? (a.containerName as unknown[]).map(String)\n : [String(a.containerName)];\n const containers = rawNames\n .map((n) => n.replace(/[^a-zA-Z0-9._-]/g, \"\"))\n .filter((n) => n.length > 0);\n if (containers.length === 0) {\n return {\n content: [\n { type: \"text\", text: \"Error: no valid containerName provided\" },\n ],\n };\n }\n\n const followSeconds = Math.max(\n 0,\n Math.min(300, Number(a.followSeconds) || 0),\n );\n const userTail =\n a.tail !== undefined\n ? Number(a.tail)\n : a.lines !== undefined\n ? Number(a.lines)\n : undefined;\n const tailArg =\n userTail !== undefined && Number.isFinite(userTail) && userTail >= 0\n ? userTail\n : followSeconds > 0\n ? 0\n : 100;\n const sinceRaw = typeof a.since === \"string\" ? a.since.trim() : \"\";\n const grepRaw = typeof a.grep === \"string\" ? a.grep : \"\";\n\n if (\n sinceRaw &&\n !/^\\d+[smhd]$/i.test(sinceRaw) &&\n !/^\\d{4}-\\d{2}-\\d{2}/.test(sinceRaw)\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: 'Error: invalid `since` format (expected e.g. \"10m\", \"2h\", or ISO timestamp)',\n },\n ],\n };\n }\n const sinceArg = sinceRaw ? ` --since ${posixQuote(sinceRaw)}` : \"\";\n const grepSuffix = grepRaw\n ? ` | grep -i -E ${posixQuote(grepRaw)} --line-buffered`\n : \"\";\n\n // Resolve target server list (fan-out support for \"show kong logs across all servers\").\n const targetIds: string[] =\n Array.isArray(a.serverIds) && a.serverIds.length > 0\n ? (a.serverIds as unknown[]).map(String)\n : a.serverId\n ? [String(a.serverId)]\n : [];\n if (targetIds.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: pass either `serverId` or `serverIds[]`\",\n },\n ],\n };\n }\n const parallelism = Math.max(\n 1,\n Math.min(20, Number(a.parallelism) || 5),\n );\n\n const wallSeconds = followSeconds > 0 ? followSeconds : 30;\n const followFlag = followSeconds > 0 ? \" -f\" : \"\";\n\n // Build the `docker logs` invocation — same shell command for every\n // server. Single-container mode produces unprefixed output; multi\n // adds [name] prefixes so streams stay distinguishable.\n const buildCmd = (): string => {\n if (containers.length === 1) {\n const c = containers[0];\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\n return `timeout --signal=INT ${wallSeconds} sh -c ${posixQuote(inner)}`;\n }\n const subShells = containers.map((c) => {\n const inner = `docker logs${followFlag} --tail ${tailArg}${sinceArg} ${c} 2>&1${grepSuffix}`;\n return `(${inner} | sed -u -e ${posixQuote(`s/^/[${c}] /`)})`;\n });\n const innerCmd = subShells.join(\" & \") + \" & wait\";\n return `timeout --signal=INT ${wallSeconds} sh -c ${posixQuote(innerCmd)}`;\n };\n const cmd = buildCmd();\n\n const probeOne = async (\n serverId: string,\n ): Promise<{\n serverId: string;\n serverName: string;\n result: SshResult;\n }> => {\n const { conn, proxy } = await getServerConnection(serverId);\n conn.timeout = (wallSeconds + 10) * 1000;\n const result = await sshExec(conn, cmd, proxy);\n const cached = KNOWN_SERVER_NAMES.get(serverId);\n return {\n serverId,\n serverName: cached?.name || serverId.slice(0, 8),\n result,\n };\n };\n\n const acceptableCode = (code: number) =>\n code === 0 ||\n code === 124 ||\n code === 130 ||\n code === 143 ||\n (!!grepRaw && code === 1);\n\n // Single-server: keep the original (unprefixed) output for back-compat.\n if (targetIds.length === 1) {\n const r = await probeOne(targetIds[0] as string);\n const result = r.result;\n // Combined output: docker pipes stderr→stdout via `2>&1`, so the\n // \"No such container\" error lives in stdout. Look for it explicitly.\n const combined = `${result.stdout}\\n${result.stderr}`;\n const noSuchMatch = /No such container:\\s*(\\S+)/i.exec(combined);\n const fuzzyHint = (): string => {\n if (!noSuchMatch) return \"\";\n const known = getKnownContainers(targetIds[0] as string);\n if (!known?.length) return \"\";\n const hits = suggestSimilar(noSuchMatch[1] as string, known);\n return hits.length\n ? `\\n(hint) Did you mean: ${hits.join(\", \")}?`\n : \"\";\n };\n\n if (!acceptableCode(result.exitCode) && !result.stdout) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error (exit ${result.exitCode}): ${result.stderr || \"(no output)\"}${fuzzyHint()}`,\n },\n ],\n };\n }\n // Even when stdout has data, surface the fuzzy hint if docker reported\n // \"No such container\" — otherwise the LLM mistakes the error for log lines.\n const note =\n result.exitCode === 124\n ? `\\n(note: command exceeded ${wallSeconds}s wall budget; partial output)`\n : \"\";\n return {\n content: [\n {\n type: \"text\",\n text:\n (result.stdout || \"(no log lines matched)\") +\n note +\n fuzzyHint(),\n },\n ],\n };\n }\n\n // Fan-out: per-server section. Each server's stdout is shown verbatim\n // (already [name]-prefixed if multi-container).\n const perServer: Awaited<ReturnType<typeof probeOne>>[] = [];\n for (let i = 0; i < targetIds.length; i += parallelism) {\n const batch = targetIds.slice(i, i + parallelism);\n const chunk = await Promise.all(batch.map(probeOne));\n perServer.push(...chunk);\n }\n const sections: string[] = [];\n let okCount = 0;\n for (const ps of perServer) {\n if (acceptableCode(ps.result.exitCode) || ps.result.stdout) {\n okCount++;\n const note =\n ps.result.exitCode === 124\n ? ` (timed out after ${wallSeconds}s; partial)`\n : \"\";\n sections.push(`=== ${ps.serverName}${note} ===`);\n sections.push(ps.result.stdout || \"(no log lines matched)\");\n } else {\n sections.push(\n `=== ${ps.serverName} === !! exit ${ps.result.exitCode}: ${ps.result.stderr.trim().slice(0, 200) || \"(no output)\"}`,\n );\n }\n }\n sections.push(\n `--- fan-out summary: ${okCount}/${perServer.length} server(s) returned logs ---`,\n );\n return { content: [{ type: \"text\", text: sections.join(\"\\n\") }] };\n }\n\n case \"docker-exec\": {\n const container = String(a.container).replace(/[^a-zA-Z0-9._-]/g, \"\");\n if (!container)\n return {\n content: [{ type: \"text\", text: \"Error: invalid container name\" }],\n };\n const command = String(a.command);\n const args = Array.isArray(a.args)\n ? (a.args as unknown[]).map(String)\n : [];\n const stdin = typeof a.stdin === \"string\" ? a.stdin : undefined;\n const interactive = a.interactive === true;\n const workdir =\n typeof a.workdir === \"string\" && a.workdir ? [\"-w\", a.workdir] : [];\n const user = typeof a.user === \"string\" && a.user ? [\"-u\", a.user] : [];\n\n // Flag matrix:\n // - stdin given: -i (attach stdin)\n // - interactive: -t (allocate TTY) so commands like psql / mysql / bash\n // that probe `isatty(stdout)` produce human-friendly output AND don't\n // complain (\"the input device is not a TTY\"). Combine with -i for full\n // interactive use; -t alone is allowed for tty-only programs.\n const flags: string[] = [];\n if (stdin !== undefined || interactive) flags.push(\"-i\");\n if (interactive) flags.push(\"-t\");\n\n // docker exec [-it] [-w DIR] [-u USER] CONTAINER CMD [ARG ...]\n const dockerArgs = [\n ...flags,\n ...workdir,\n ...user,\n container,\n command,\n ...args,\n ];\n const fullCmd = buildPosixCommand(\"docker\", [\"exec\", ...dockerArgs]);\n\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n if (a.timeout) conn.timeout = Number(a.timeout);\n const result = await sshExec(conn, fullCmd, proxy, {\n stdin,\n pty: interactive,\n });\n const output = [`Exit code: ${result.exitCode}`];\n if (result.stdout) output.push(`--- stdout ---\\n${result.stdout}`);\n if (result.stderr) {\n let stderrOut = result.stderr;\n // Fuzzy hint: docker emits \"No such container: <name>\" when the\n // identifier is wrong. Use the docker-list cache (if recent) for\n // a \"did you mean?\" suggestion.\n const noSuch = /No such container:\\s*(\\S+)/i.exec(result.stderr);\n if (noSuch) {\n const known = getKnownContainers(String(a.serverId));\n if (known && known.length) {\n const hits = suggestSimilar(noSuch[1] as string, known);\n if (hits.length)\n stderrOut += `\\n(hint) Did you mean: ${hits.join(\", \")}?`;\n }\n }\n output.push(`--- stderr ---\\n${stderrOut}`);\n }\n return { content: [{ type: \"text\", text: output.join(\"\\n\") }] };\n }\n\n case \"docker-compose\": {\n const projectPath = String(a.projectPath);\n if (!projectPath || !projectPath.startsWith(\"/\")) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: projectPath must be an absolute path\",\n },\n ],\n };\n }\n const action = String(a.action);\n const allowedActions = [\n \"up\",\n \"down\",\n \"restart\",\n \"logs\",\n \"ps\",\n \"pull\",\n \"build\",\n ] as const;\n if (\n !allowedActions.includes(action as (typeof allowedActions)[number])\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: invalid action (allowed: ${allowedActions.join(\", \")})`,\n },\n ],\n };\n }\n const service =\n typeof a.service === \"string\" && a.service ? a.service : \"\";\n const tail = Number(a.tail) > 0 ? Number(a.tail) : 200;\n\n let composeArgs: string[];\n switch (action) {\n case \"up\":\n composeArgs = service ? [\"up\", \"-d\", service] : [\"up\", \"-d\"];\n break;\n case \"down\":\n composeArgs = service ? [\"down\", service] : [\"down\"];\n break;\n case \"restart\":\n composeArgs = service ? [\"restart\", service] : [\"restart\"];\n break;\n case \"logs\":\n composeArgs = service\n ? [\"logs\", \"--no-color\", `--tail=${tail}`, service]\n : [\"logs\", \"--no-color\", `--tail=${tail}`];\n break;\n case \"ps\":\n composeArgs = service ? [\"ps\", service] : [\"ps\"];\n break;\n case \"pull\":\n composeArgs = service ? [\"pull\", service] : [\"pull\"];\n break;\n case \"build\":\n composeArgs = service ? [\"build\", service] : [\"build\"];\n break;\n default:\n composeArgs = []; // unreachable\n }\n\n const composeCmd = buildPosixCommand(\"docker\", [\n \"compose\",\n ...composeArgs,\n ]);\n const fullCmd = `cd ${posixQuote(projectPath)} && ${composeCmd} 2>&1`;\n\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n conn.timeout = Number(a.timeout) > 0 ? Number(a.timeout) : 120_000;\n const result = await sshExec(conn, fullCmd, proxy);\n const output = [\n `Exit code: ${result.exitCode} (compose ${action}${service ? ` ${service}` : \"\"} @ ${projectPath})`,\n ];\n if (result.stdout) output.push(result.stdout);\n if (result.stderr) output.push(`--- stderr ---\\n${result.stderr}`);\n return { content: [{ type: \"text\", text: output.join(\"\\n\") }] };\n }\n\n // ----- wait-for: poll until a condition holds (one tool, four types) -----\n case \"wait-for\": {\n const type = String(a.type || \"\");\n if (\n ![\"url\", \"container-health\", \"file-exists\", \"sftp-exists\"].includes(\n type,\n )\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: type must be one of: url, container-health, file-exists, sftp-exists\",\n },\n ],\n };\n }\n const timeoutSeconds = Math.max(\n 1,\n Math.min(1800, Number(a.timeout) || 120),\n );\n const intervalSeconds = Math.max(\n 1,\n Math.min(60, Number(a.intervalSeconds) || 3),\n );\n const deadline = Date.now() + timeoutSeconds * 1000;\n const trail: string[] = [];\n\n const check = async (): Promise<{ ok: boolean; observed: string }> => {\n if (type === \"url\") {\n const target = String(a.target || \"\");\n if (!target) return { ok: false, observed: \"no target url\" };\n const expectStatus = a.until !== undefined ? Number(a.until) : 200;\n try {\n const ctrl = new AbortController();\n const t = setTimeout(() => ctrl.abort(), 10_000);\n const res = await fetch(target, {\n signal: ctrl.signal,\n redirect: \"manual\",\n });\n clearTimeout(t);\n const ok =\n res.status === expectStatus ||\n (expectStatus === 200 && res.status >= 200 && res.status < 300);\n return { ok, observed: `HTTP ${res.status}` };\n } catch (e) {\n return {\n ok: false,\n observed: e instanceof Error ? e.message : String(e),\n };\n }\n }\n if (type === \"container-health\") {\n // target = container name; until = 'healthy' (default), 'running', 'exited'\n const containerName = String(a.target || \"\").replace(\n /[^a-zA-Z0-9._-]/g,\n \"\",\n );\n const until = String(a.until || \"healthy\");\n if (!containerName)\n return { ok: false, observed: \"no container name\" };\n if (!a.serverId)\n return {\n ok: false,\n observed: \"serverId is required for container-health\",\n };\n const { conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n const cmd = `docker inspect --format '{{json .State}}' ${containerName} 2>&1`;\n const r = await sshExec(conn, cmd, proxy);\n if (r.exitCode !== 0)\n return {\n ok: false,\n observed: r.stderr.trim().slice(0, 80) || \"inspect failed\",\n };\n try {\n const state = JSON.parse(r.stdout.trim()) as {\n Status?: string;\n Health?: { Status?: string };\n };\n const healthStatus = state.Health?.Status; // 'healthy' | 'unhealthy' | 'starting' | undefined\n if (until === \"healthy\") {\n return {\n ok: healthStatus === \"healthy\",\n observed: `Status=${state.Status} Health=${healthStatus || \"no-check\"}`,\n };\n }\n return {\n ok: state.Status === until,\n observed: `Status=${state.Status}`,\n };\n } catch (e) {\n return {\n ok: false,\n observed:\n \"parse error: \" +\n (e instanceof Error ? e.message : String(e)),\n };\n }\n }\n // file-exists / sftp-exists: same impl, the SFTP backend (R2 bucket\n // or SSH server) is selected by which arg is present.\n const bucket =\n typeof a.bucket === \"string\" && a.bucket ? a.bucket : \"\";\n const path = String(a.target || a.path || \"\");\n if (!path) return { ok: false, observed: \"no path\" };\n if (bucket) {\n try {\n await getR2Client().send(\n new HeadObjectCommand({ Bucket: bucket, Key: r2Key(path) }),\n );\n return { ok: true, observed: `r2://${bucket}/${path} exists` };\n } catch {\n return {\n ok: false,\n observed: `r2://${bucket}/${path} not found`,\n };\n }\n }\n if (!a.serverId)\n return {\n ok: false,\n observed: \"serverId or bucket is required for file-exists\",\n };\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n const safe = sanitizePath(path);\n const cmd = `test -e ${posixQuote(safe)} && echo OK || echo MISSING`;\n const r = await sshExec(conn, cmd, proxy);\n const ok = r.stdout.trim() === \"OK\";\n return { ok, observed: ok ? `${safe} exists` : `${safe} missing` };\n };\n\n let attempts = 0;\n let lastObserved = \"\";\n while (Date.now() < deadline) {\n attempts++;\n const r = await check();\n lastObserved = r.observed;\n trail.push(\n `[${attempts}] ${new Date().toISOString().slice(11, 19)} ${r.ok ? \"OK\" : \"..\"} ${r.observed}`,\n );\n if (r.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `Condition met after ${attempts} attempt(s) in ${((Date.now() - (deadline - timeoutSeconds * 1000)) / 1000).toFixed(1)}s.\\nLast observation: ${r.observed}\\n\\n--- trail ---\\n${trail.join(\"\\n\")}`,\n },\n ],\n };\n }\n if (Date.now() + intervalSeconds * 1000 >= deadline) break;\n await new Promise((res) => setTimeout(res, intervalSeconds * 1000));\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Timed out after ${timeoutSeconds}s without seeing condition (${attempts} probe(s)).\\nLast observation: ${lastObserved}\\n\\n--- trail ---\\n${trail.join(\"\\n\")}`,\n },\n ],\n };\n }\n\n // ----- Database -----\n case \"db-discover\": {\n const { serverId, conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n\n // Back-compat: when `include` is omitted, run the original /var/www\n // scan only. Pass `include: [\"postgres-containers\"]` to enumerate\n // vanilla Postgres Docker containers (refront / trigger / pgvector\n // dev stacks). Both modes can be combined in one call.\n const rawInclude = Array.isArray(a.include)\n ? a.include.map(String)\n : [\"www\"];\n const include = new Set(\n rawInclude.filter((m) => m === \"www\" || m === \"postgres-containers\"),\n );\n if (include.size === 0) include.add(\"www\");\n\n const sections: string[] = [];\n\n if (include.has(\"www\")) {\n const sites = await discoverSiteDatabases(conn, proxy);\n if (!sites.length) {\n sections.push(\"## /var/www\\n(none)\");\n } else {\n const lines = sites.map(\n (s) =>\n `${s.sitePath} [${s.appType}] db=${s.database} user=${s.user} host=${s.host}:${s.port}`,\n );\n sections.push(`## /var/www (${sites.length})\\n${lines.join(\"\\n\")}`);\n }\n }\n\n if (include.has(\"postgres-containers\")) {\n const containers = await discoverPostgresContainers(conn, proxy);\n // Prime the per-container creds cache so subsequent db-* calls\n // on this server don't need to pass dbName / dbUser.\n for (const c of containers) {\n cachePostgresContainerCreds(serverId, c.container, {\n dbName: c.db,\n dbUser: c.user,\n hasPassword: c.hasPassword,\n });\n }\n if (!containers.length) {\n sections.push(\n \"## Postgres containers\\n(none — no running container exposes POSTGRES_USER/POSTGRES_DB)\",\n );\n } else {\n const lines = containers.map(\n (c) =>\n `${c.container} db=${c.db} user=${c.user} hostPort=${c.hostPort ?? \"(internal-only)\"} password=${c.hasPassword ? \"set\" : \"unset\"}`,\n );\n sections.push(\n `## Postgres containers (${containers.length})\\n${lines.join(\"\\n\")}\\n\\nTip: pass just \\`containerName\\` to \\`db-query\\` / \\`db-apply-migration\\` / \\`db-list-migrations\\` — dbName + dbUser are auto-resolved from the container env (cached for 1h per server).`,\n );\n }\n }\n\n return { content: [{ type: \"text\", text: sections.join(\"\\n\\n\") }] };\n }\n\n case \"db-tables\": {\n const { serverId, conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n const containerName =\n typeof a.containerName === \"string\" && a.containerName\n ? a.containerName\n : \"\";\n\n if (containerName) {\n let dbUser = typeof a.dbUser === \"string\" && a.dbUser ? a.dbUser : \"\";\n let dbName = typeof a.dbName === \"string\" && a.dbName ? a.dbName : \"\";\n if (!dbUser || !dbName) {\n const creds = await resolvePostgresContainerCreds(\n conn,\n proxy,\n serverId,\n containerName,\n );\n if (!dbUser) dbUser = creds.dbUser;\n if (!dbName) dbName = creds.dbName;\n }\n const sqlText =\n `SELECT n.nspname AS schema,\\n` +\n ` c.relname AS \"table\",\\n` +\n ` pg_size_pretty(pg_total_relation_size(c.oid)) AS size,\\n` +\n ` c.reltuples::bigint AS estimated_rows\\n` +\n `FROM pg_class c\\n` +\n `JOIN pg_namespace n ON n.oid = c.relnamespace\\n` +\n `WHERE c.relkind = 'r'\\n` +\n ` AND n.nspname NOT IN ('pg_catalog', 'information_schema')\\n` +\n `ORDER BY pg_total_relation_size(c.oid) DESC;\\n`;\n const res = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n sqlText,\n \"\",\n );\n const output =\n res.stdout.trim() || res.stderr.trim() || \"(no output)\";\n if (res.exitCode !== 0 && !res.stdout) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error (exit ${res.exitCode}): ${output}`,\n },\n ],\n };\n }\n return {\n content: [{ type: \"text\", text: output || \"No tables found\" }],\n };\n }\n\n if (!a.sitePath) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: pass `sitePath` (MySQL autodiscover) or `containerName` (Postgres container).\",\n },\n ],\n };\n }\n const sqlText =\n \"SELECT TABLE_NAME, ENGINE, TABLE_ROWS, ROUND(DATA_LENGTH/1024/1024, 2) AS `Size (MB)`, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME\";\n const output = await execSiteMysql(\n conn,\n String(a.sitePath),\n sqlText,\n proxy,\n );\n return {\n content: [{ type: \"text\", text: output || \"No tables found\" }],\n };\n }\n\n case \"db-query\": {\n // Engine routing. Default behaviour (mysql + sitePath) is unchanged\n // for back-compat. Pass `containerName` to query a DB inside a Docker\n // container — engine defaults to postgres in that case (covers the\n // self-hosted Supabase / Trigger.dev stacks).\n const containerName =\n typeof a.containerName === \"string\" && a.containerName\n ? a.containerName.replace(/[^a-zA-Z0-9._-]/g, \"\")\n : \"\";\n const explicitEngine =\n a.engine === \"mysql\" ||\n a.engine === \"postgres\" ||\n a.engine === \"mssql\"\n ? a.engine\n : null;\n const engine: \"mysql\" | \"postgres\" | \"mssql\" =\n explicitEngine || (containerName ? \"postgres\" : \"mysql\");\n\n // Schema-introspection shortcut. Replaces the old db-describe tool\n // and works for all three engines. Sanitises the table identifier\n // before string interpolation. \"*\" lists all tables.\n const describeArg =\n typeof a.describe === \"string\" ? a.describe.trim() : \"\";\n\n // Result-size guardrail + EXPLAIN mode. Both rewrite the query string\n // before it hits the engine-specific path below.\n const explainMode = a.explain === true;\n const maxRowsRaw = a.maxRows === undefined ? 1000 : Number(a.maxRows);\n const maxRows = Math.min(\n Math.max(Number.isFinite(maxRowsRaw) ? maxRowsRaw : 0, 0),\n 10000,\n );\n\n let rawQuery: string;\n if (describeArg) {\n rawQuery = buildDescribeSql(describeArg, engine);\n } else {\n rawQuery = String(a.query ?? \"\").trim();\n if (!rawQuery)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: query (or describe) is required\",\n },\n ],\n };\n }\n\n // Destructive ops (DROP / TRUNCATE / ALTER…DROP / naked DELETE) are\n // blocked by default to protect against accidental data loss. Schema\n // migrations should go through `db-apply-migration` (audit + drift\n // detection). As a last-resort escape hatch the caller can pass the\n // literal phrase below; we then skip the gate and surface a banner\n // in the response footer so the bypass is visible.\n const allowDestructivePhrase = \"yes-i-understand-this-is-not-logged\";\n const allowDestructive = a.allowDestructive === allowDestructivePhrase;\n if (!allowDestructive && !describeArg) {\n try {\n assertSafeSql(rawQuery);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: \"text\",\n text:\n `${msg}\\n\\n` +\n `For schema migrations use \\`db-apply-migration\\` — it allows DDL and records every change in the \\`_mcp_migrations\\` ledger for audit and idempotency.\\n` +\n `For a one-off ad-hoc destructive query, pass \\`allowDestructive: \"${allowDestructivePhrase}\"\\`.`,\n },\n ],\n };\n }\n }\n\n let query = rawQuery.replace(/;\\s*$/, \"\");\n let appliedLimit = false;\n // Atomic-multi-statement mode: wrap in BEGIN/COMMIT so a failure in\n // statement N rolls back statements 1..N-1. Skipped in EXPLAIN mode\n // (would just plan the BEGIN), on MSSQL (different syntax), and when\n // using describe shortcut (introspection is read-only).\n const wrapTransaction =\n a.transaction === true &&\n !explainMode &&\n !describeArg &&\n engine !== \"mssql\";\n\n if (explainMode && !describeArg) {\n if (engine === \"mssql\") {\n // mssql has no inline EXPLAIN; prepend SET SHOWPLAN_TEXT ON and\n // run the statement so sqlcmd returns the plan instead of rows.\n query = `SET SHOWPLAN_TEXT ON;\\n${query}`;\n } else {\n // postgres + mysql both accept \"EXPLAIN <statement>\".\n query = `EXPLAIN ${query}`;\n }\n } else if (maxRows > 0 && !describeArg) {\n // Only auto-LIMIT a single bare SELECT (or WITH ... SELECT) that\n // doesn't already have its own LIMIT / TOP. Skip mssql since LIMIT\n // syntax differs (TOP / OFFSET FETCH).\n const isSelect = /^\\s*(with\\b[\\s\\S]+?\\bselect\\b|select\\b)/i.test(\n query,\n );\n const alreadyLimited =\n /\\blimit\\s+\\d+\\b/i.test(query) || /\\btop\\s*\\(?\\s*\\d+/i.test(query);\n if (isSelect && !alreadyLimited && engine !== \"mssql\") {\n query = `${query}\\nLIMIT ${maxRows + 1}`; // +1 so we can detect truncation\n appliedLimit = true;\n }\n }\n\n if (wrapTransaction) {\n // Strip a stray trailing semicolon, then wrap. ON_ERROR_STOP is\n // already set on the psql container path so the COMMIT is never\n // reached if any inner statement fails.\n query = `BEGIN;\\n${query.replace(/;\\s*$/, \"\")};\\nCOMMIT;`;\n }\n\n const txBanner = wrapTransaction\n ? `\\n\\n[transaction] wrapped in BEGIN/COMMIT — all statements committed atomically.`\n : \"\";\n\n const destructiveBanner = allowDestructive\n ? \"\\n\\n[allowDestructive] safety gate bypassed for this query — NOT recorded in any audit ledger. Consider db-apply-migration for repeatable schema changes.\"\n : \"\";\n\n // Path A: existing MySQL-via-/var/www autodiscover. Always engine=mysql.\n if (!containerName && engine === \"mysql\") {\n if (!a.sitePath)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: sitePath is required for mysql autodiscover (or pass containerName + engine for direct DB queries)\",\n },\n ],\n };\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n const output = await execSiteMysql(\n conn,\n String(a.sitePath),\n query,\n proxy,\n );\n const footer = formatDbQueryFooter(\n output,\n appliedLimit,\n maxRows,\n explainMode,\n );\n return {\n content: [\n {\n type: \"text\",\n text:\n (output || \"Query executed successfully (no output)\") +\n footer +\n destructiveBanner +\n txBanner,\n },\n ],\n };\n }\n\n // Path B: docker exec into a container with the appropriate client.\n // Query is piped via STDIN to avoid quoting hell with `, $, ; etc.\n if (!containerName) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: engine=${engine} requires containerName (the docker container running the DB server, e.g. \"supabase-db\" or \"trigger-postgres\")`,\n },\n ],\n };\n }\n let dbName =\n typeof a.dbName === \"string\" && a.dbName\n ? a.dbName.replace(/[^a-zA-Z0-9_-]/g, \"\")\n : \"\";\n let dbUser =\n typeof a.dbUser === \"string\" && a.dbUser\n ? a.dbUser.replace(/[^a-zA-Z0-9_-]/g, \"\")\n : \"\";\n const { serverId, conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n\n // Auto-resolve dbName / dbUser from the container's POSTGRES_USER /\n // POSTGRES_DB env vars when the caller omits them (postgres only;\n // mssql has no equivalent and mysql via container is rarely used\n // without explicit creds). Cached for 1h per (serverId, container).\n if (engine === \"postgres\" && (!dbName || !dbUser)) {\n const creds = await resolvePostgresContainerCreds(\n conn,\n proxy,\n serverId,\n containerName,\n );\n if (!dbName) dbName = creds.dbName.replace(/[^a-zA-Z0-9_-]/g, \"\");\n if (!dbUser) dbUser = creds.dbUser.replace(/[^a-zA-Z0-9_-]/g, \"\");\n }\n\n let cmd: string;\n let stdinPayload: string | undefined;\n if (engine === \"postgres\") {\n // psql: -t (tuples-only) -A (unaligned) is great for parsing; use\n // -P expanded=auto for human-friendly default.\n const user = dbUser || \"postgres\";\n const db = dbName || \"postgres\";\n // Pipe the query in via stdin so we don't need to escape it.\n cmd = `docker exec -i ${containerName} psql -U ${user} -d ${db} -P pager=off`;\n stdinPayload = query.endsWith(\";\") ? query : `${query};`;\n } else if (engine === \"mssql\") {\n // sqlcmd path (assumes mssql-tools in container). Caller provides\n // dbUser + dbPass (we *only* take dbPass here for mssql since\n // it isn't auto-discoverable like Postgres trust).\n const user = dbUser || \"sa\";\n const dbPass = typeof a.dbPass === \"string\" ? a.dbPass : \"\";\n if (!dbPass)\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: mssql requires dbPass (sqlcmd has no equivalent of pg trust auth)\",\n },\n ],\n };\n const dbArg = dbName ? `-d ${dbName} ` : \"\";\n // Use stdin via -i /dev/stdin pattern; sqlcmd reads from stdin when no -Q given.\n cmd = `docker exec -i -e MSSQL_SA_PASSWORD=${posixQuote(dbPass)} ${containerName} /opt/mssql-tools18/bin/sqlcmd -S localhost -U ${user} -P \"$MSSQL_SA_PASSWORD\" -C ${dbArg}-h -1`;\n stdinPayload = query.endsWith(\";\")\n ? `${query}\\nGO\\n`\n : `${query};\\nGO\\n`;\n } else {\n // engine === 'mysql' but with containerName: useful for dockerised\n // MySQL outside of /var/www, e.g. a dev stack.\n const user = dbUser || \"root\";\n const db = dbName ? ` ${dbName}` : \"\";\n const dbPass = typeof a.dbPass === \"string\" ? a.dbPass : \"\";\n const passArg = dbPass ? `-p${posixQuote(dbPass)} ` : \"\";\n cmd = `docker exec -i ${containerName} mysql -t -u ${user} ${passArg}${db}`;\n stdinPayload = query.endsWith(\";\") ? query : `${query};`;\n }\n\n const result = await sshExec(conn, cmd, proxy, { stdin: stdinPayload });\n const output =\n result.stdout.trim() || result.stderr.trim() || \"(no output)\";\n if (result.exitCode !== 0 && !result.stdout) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error (exit ${result.exitCode}, ${engine}): ${output}`,\n },\n ],\n };\n }\n const footer = formatDbQueryFooter(\n output,\n appliedLimit,\n maxRows,\n explainMode,\n );\n return {\n content: [\n {\n type: \"text\",\n text: output + footer + destructiveBanner + txBanner,\n },\n ],\n };\n }\n\n case \"db-apply-migration\": {\n const containerName = String(a.containerName || \"\").replace(\n /[^a-zA-Z0-9._-]/g,\n \"\",\n );\n if (!containerName)\n return {\n content: [\n { type: \"text\", text: \"Error: containerName is required\" },\n ],\n };\n // dbUser / dbName default to whatever the container's POSTGRES_USER\n // / POSTGRES_DB env vars say (resolved + cached below). Caller can\n // still pass explicit overrides — common when an instance hosts\n // multiple databases.\n let dbUser = (\n typeof a.dbUser === \"string\" && a.dbUser ? a.dbUser : \"\"\n ).replace(/[^a-zA-Z0-9_-]/g, \"\");\n let dbName = (\n typeof a.dbName === \"string\" && a.dbName ? a.dbName : \"\"\n ).replace(/[^a-zA-Z0-9_-]/g, \"\");\n const name = String(a.name || \"\").trim();\n if (!name)\n return {\n content: [\n {\n type: \"text\",\n text: 'Error: name is required (e.g. \"20260517120000_add_foo\")',\n },\n ],\n };\n if (!/^[\\w.@:+\\-]+$/.test(name) || name.length > 200) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: name must be ≤200 chars and contain only [A-Za-z0-9_.@:+-]\",\n },\n ],\n };\n }\n const noTransaction = a.noTransaction === true;\n const force = a.force === true;\n const recordOnly = a.recordOnly === true;\n const t0 = Date.now();\n const took = () => `${((Date.now() - t0) / 1000).toFixed(2)}s`;\n\n // Exactly one of sql / localFile / remoteFile is required. We\n // resolve all three into a single SQL string before computing\n // the sha256 so the hash is content-stable regardless of source.\n const sources = [\n typeof a.sql === \"string\" && a.sql ? \"sql\" : null,\n typeof a.localFile === \"string\" && a.localFile ? \"localFile\" : null,\n typeof a.remoteFile === \"string\" && a.remoteFile\n ? \"remoteFile\"\n : null,\n ].filter((v): v is string => v !== null);\n if (sources.length !== 1) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: pass exactly one of \\`sql\\`, \\`localFile\\`, or \\`remoteFile\\` (got ${sources.length || \"none\"}: ${sources.join(\", \") || \"—\"})`,\n },\n ],\n };\n }\n\n const { serverId, conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n\n if (!dbUser || !dbName) {\n const creds = await resolvePostgresContainerCreds(\n conn,\n proxy,\n serverId,\n containerName,\n );\n if (!dbUser)\n dbUser = creds.dbUser.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n if (!dbName)\n dbName = creds.dbName.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n }\n\n let migrationSql: string;\n if (typeof a.sql === \"string\" && a.sql) {\n migrationSql = a.sql;\n } else if (typeof a.localFile === \"string\" && a.localFile) {\n const p = a.localFile;\n if (!isAbsolute(p) && !p.startsWith(\"./\") && !p.startsWith(\"../\")) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: localFile must be an absolute path or start with ./ or ../\",\n },\n ],\n };\n }\n try {\n migrationSql = await readFile(p, \"utf8\");\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error reading localFile \"${p}\": ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n } else {\n // remoteFile: cat the file on the server (works through the proxy).\n const remotePath = String(a.remoteFile);\n if (!remotePath.startsWith(\"/\")) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Error: remoteFile must be an absolute path on the SSH server\",\n },\n ],\n };\n }\n const catRes = await sshExec(\n conn,\n `cat ${posixQuote(remotePath)}`,\n proxy,\n );\n if (catRes.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error reading remoteFile \"${remotePath}\" on server: ${catRes.stderr || `exit ${catRes.exitCode}`}`,\n },\n ],\n };\n }\n migrationSql = catRes.stdout;\n }\n\n const normalised = normaliseMigrationSql(migrationSql);\n if (!normalised.trim()) {\n return {\n content: [{ type: \"text\", text: \"Error: resolved SQL is empty\" }],\n };\n }\n const sha = migrationSha256(migrationSql);\n\n // Roundtrip 1: ensure ledger exists. We discard output — psql's\n // command-tag for CREATE TABLE leaks through `-tA` (which only\n // affects result rows, not command tags) and previously contaminated\n // the sha-probe parse on a clean install, triggering a false-positive\n // \"drift detected\" for every first apply.\n const ddl = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n `${MIGRATION_LEDGER_DDL}\\n`,\n \"\",\n );\n if (ddl.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error initialising ledger on ${containerName} (${dbName}): ${ddl.stderr || ddl.stdout || `exit ${ddl.exitCode}`}`,\n },\n ],\n };\n }\n\n // Roundtrip 2: pure SELECT. With `-tA` the output is either\n // completely empty (zero rows) or a single 64-char lowercase hex\n // digest. The regex filter guards against stray notices / banners.\n const probeSelect = `SELECT sha256 FROM _mcp_migrations WHERE name = ${dollarQuote(name)};\\n`;\n const probe = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n probeSelect,\n \"-tA\",\n );\n if (probe.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error reading ledger on ${containerName} (${dbName}): ${probe.stderr || probe.stdout || `exit ${probe.exitCode}`}`,\n },\n ],\n };\n }\n const existingSha =\n probe.stdout\n .split(\"\\n\")\n .map((l) => l.trim())\n .find((l) => /^[0-9a-f]{64}$/.test(l)) || \"\";\n\n if (existingSha && existingSha === sha) {\n return {\n content: [\n {\n type: \"text\",\n text: `[noop] Migration \"${name}\" already applied on ${containerName}/${dbName} (sha256 matches, took ${took()}).\\nLedger sha: ${sha.slice(0, 12)}…`,\n },\n ],\n };\n }\n if (existingSha && existingSha !== sha && !force) {\n return {\n content: [\n {\n type: \"text\",\n text:\n `[drift] Migration \"${name}\" exists in ledger with DIFFERENT sha256 (took ${took()}).\\n` +\n ` ledger sha: ${existingSha.slice(0, 12)}…\\n` +\n ` new sha: ${sha.slice(0, 12)}…\\n\\n` +\n `This usually means the migration file was edited after it was first applied. Inspect the differences and either revert the source file or call again with \\`force: true\\` to overwrite the ledger entry (the SQL will be re-executed).`,\n },\n ],\n };\n }\n\n // Apply phase. Wrap in BEGIN/COMMIT unless caller opted out (needed\n // for CONCURRENTLY / ALTER TYPE ADD VALUE / VACUUM). In no-transaction\n // mode we record the ledger in a separate roundtrip after the user\n // SQL succeeds — accepted race window since this is a dev tool.\n const appliedBy = `${authContext!.apiKeyName} (${authContext!.roleName})`;\n const ledgerInsert =\n `INSERT INTO _mcp_migrations (name, sha256, applied_by) VALUES (${dollarQuote(name)}, ${dollarQuote(sha)}, ${dollarQuote(appliedBy)})\\n` +\n `ON CONFLICT (name) DO UPDATE SET sha256 = EXCLUDED.sha256, applied_at = now(), applied_by = EXCLUDED.applied_by;\\n`;\n\n // recordOnly: backfill the ledger for a migration that was already\n // applied out-of-band (manual psql session, deploy script, etc.).\n // Skips the user SQL entirely; sha256 is still computed from the\n // provided SQL so the ledger reflects what was actually run.\n if (recordOnly) {\n const record = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n ledgerInsert,\n \"\",\n );\n if (record.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text:\n `[failed] Ledger insert for \"${name}\" failed (recordOnly=true, no SQL was executed).\\n` +\n `psql exit: ${record.exitCode}\\n` +\n (record.stderr\n ? `--- stderr ---\\n${record.stderr}\\n`\n : \"\") +\n (record.stdout ? `--- stdout ---\\n${record.stdout}` : \"\"),\n },\n ],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text:\n `[recorded] \"${name}\" written to ledger on ${containerName}/${dbName} WITHOUT executing the SQL (recordOnly=true${existingSha ? \", overwrote existing entry\" : \"\"}, took ${took()}).\\n` +\n `ledger sha: ${sha.slice(0, 12)}…`,\n },\n ],\n };\n }\n\n if (noTransaction) {\n // Step 1: run the user SQL on its own connection (no wrapper).\n const apply = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n normalised,\n \"\",\n );\n if (apply.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text:\n `[failed] Migration \"${name}\" did not apply cleanly (noTransaction=true, no ledger entry recorded).\\n` +\n `psql exit: ${apply.exitCode}\\n` +\n (apply.stderr ? `--- stderr ---\\n${apply.stderr}\\n` : \"\") +\n (apply.stdout ? `--- stdout ---\\n${apply.stdout}` : \"\"),\n },\n ],\n };\n }\n // Step 2: record in the ledger.\n const record = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n ledgerInsert,\n \"\",\n );\n if (record.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text:\n `[partial] Migration \"${name}\" applied but ledger insert FAILED. Re-run with \\`force: true\\` after the issue is resolved.\\n` +\n `psql exit: ${record.exitCode}\\n` +\n (record.stderr\n ? `--- stderr ---\\n${record.stderr}\\n`\n : \"\") +\n (record.stdout ? `--- stdout ---\\n${record.stdout}` : \"\"),\n },\n ],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text:\n `[applied] \"${name}\" on ${containerName}/${dbName} (noTransaction=true${existingSha ? \", force\" : \"\"}, took ${took()}).\\n` +\n `ledger sha: ${sha.slice(0, 12)}…\\n` +\n (apply.stdout\n ? `--- output ---\\n${apply.stdout.trim()}`\n : \"(no output)\"),\n },\n ],\n };\n }\n\n const wrappedSql = `BEGIN;\\n${normalised}\\n${ledgerInsert}COMMIT;\\n`;\n const res = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n wrappedSql,\n \"\",\n );\n if (res.exitCode !== 0) {\n return {\n content: [\n {\n type: \"text\",\n text:\n `[failed] Migration \"${name}\" did not apply (transaction rolled back, ledger unchanged).\\n` +\n `psql exit: ${res.exitCode}\\n` +\n (res.stderr ? `--- stderr ---\\n${res.stderr}\\n` : \"\") +\n (res.stdout ? `--- stdout ---\\n${res.stdout}` : \"\"),\n },\n ],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text:\n `[applied] \"${name}\" on ${containerName}/${dbName}${existingSha ? \" (forced overwrite)\" : \"\"} (took ${took()}).\\n` +\n `ledger sha: ${sha.slice(0, 12)}…\\n` +\n (res.stdout\n ? `--- output ---\\n${res.stdout.trim()}`\n : \"(no output)\"),\n },\n ],\n };\n }\n\n case \"db-list-migrations\": {\n const containerName = String(a.containerName || \"\").replace(\n /[^a-zA-Z0-9._-]/g,\n \"\",\n );\n if (!containerName)\n return {\n content: [\n { type: \"text\", text: \"Error: containerName is required\" },\n ],\n };\n let dbUser = (\n typeof a.dbUser === \"string\" && a.dbUser ? a.dbUser : \"\"\n ).replace(/[^a-zA-Z0-9_-]/g, \"\");\n let dbName = (\n typeof a.dbName === \"string\" && a.dbName ? a.dbName : \"\"\n ).replace(/[^a-zA-Z0-9_-]/g, \"\");\n const limitRaw = Number(a.limit);\n const limit = Math.min(\n Math.max(\n Number.isFinite(limitRaw) && limitRaw > 0\n ? Math.floor(limitRaw)\n : 50,\n 1,\n ),\n 500,\n );\n\n const { serverId, conn, proxy } = await getServerConnection(\n String(a.serverId),\n );\n if (!dbUser || !dbName) {\n const creds = await resolvePostgresContainerCreds(\n conn,\n proxy,\n serverId,\n containerName,\n );\n if (!dbUser)\n dbUser = creds.dbUser.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n if (!dbName)\n dbName = creds.dbName.replace(/[^a-zA-Z0-9_-]/g, \"\") || \"postgres\";\n }\n // Plain SELECT — no DO-block guard (which leaked `DO` as a command\n // tag above the table). If the ledger doesn't exist yet psql emits\n // `relation \"_mcp_migrations\" does not exist` to stderr; the\n // friendly-empty branch below catches that string. Full sha256 is\n // returned (no substr) so the caller can grep / cross-reference.\n const sqlText =\n `SELECT name, sha256, applied_at, applied_by\\n` +\n `FROM _mcp_migrations\\n` +\n `ORDER BY applied_at DESC\\n` +\n `LIMIT ${limit};\\n`;\n const res = await psqlInContainer(\n conn,\n proxy,\n containerName,\n dbUser,\n dbName,\n sqlText,\n \"\",\n );\n if (res.exitCode !== 0) {\n // Ledger missing → friendly empty response.\n if (\n /relation \"_mcp_migrations\" does not exist/.test(res.stderr) ||\n /relation \"_mcp_migrations\" does not exist/.test(res.stdout)\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: `No \\`_mcp_migrations\\` ledger on ${containerName}/${dbName} yet. Apply your first migration with \\`db-apply-migration\\` to create it.`,\n },\n ],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Error (exit ${res.exitCode}): ${res.stderr || res.stdout}`,\n },\n ],\n };\n }\n const output = res.stdout.trim();\n return {\n content: [\n {\n type: \"text\",\n text:\n output ||\n `Ledger exists on ${containerName}/${dbName} but is empty.`,\n },\n ],\n };\n }\n\n // ----- Env Config -----\n case \"env-list\": {\n let stageFilterIds: string[] | null = null;\n if (a.releaseProfile) {\n const { stageIds } = await resolveReleaseProfileStageIds(\n String(a.releaseProfile),\n );\n stageFilterIds = stageIds;\n }\n\n const data = stageFilterIds\n ? await db.execute<EnvConfigListRow>(sql`\n SELECT id, app_name, environment, description, updated_at, release_profile_stage_id\n FROM env_config\n WHERE release_profile_stage_id = ANY(${uuidArrayParam(stageFilterIds)})\n ORDER BY app_name, environment\n `)\n : await db.execute<EnvConfigListRow>(sql`\n SELECT id, app_name, environment, description, updated_at, release_profile_stage_id\n FROM env_config\n ORDER BY app_name, environment\n `);\n\n const stageIds = data\n .map((e) => e.release_profile_stage_id)\n .filter((v): v is string => Boolean(v));\n const profileNames = await getProfileNamesForStageIds(stageIds);\n\n const lines = data.map((e) => {\n const profile = e.release_profile_stage_id\n ? profileNames[e.release_profile_stage_id] || \"unknown\"\n : \"unlinked\";\n return `${e.app_name}/${e.environment} [${profile}] (updated: ${e.updated_at})`;\n });\n return {\n content: [\n {\n type: \"text\",\n text: lines.length\n ? lines.join(\"\\n\")\n : \"No environment configs stored\",\n },\n ],\n };\n }\n\n case \"env-get\": {\n const appName = String(a.appName);\n const environment = String(a.environment);\n\n let stageFilterIds: string[] | null = null;\n if (a.releaseProfile) {\n const { stageIds } = await resolveReleaseProfileStageIds(\n String(a.releaseProfile),\n );\n stageFilterIds = stageIds;\n }\n\n const data = stageFilterIds\n ? await db.execute<EnvConfigEncryptedRow>(sql`\n SELECT env_data_encrypted, release_profile_stage_id\n FROM env_config\n WHERE app_name = ${appName}\n AND environment = ${environment}\n AND release_profile_stage_id = ANY(${uuidArrayParam(stageFilterIds)})\n `)\n : await db.execute<EnvConfigEncryptedRow>(sql`\n SELECT env_data_encrypted, release_profile_stage_id\n FROM env_config\n WHERE app_name = ${appName}\n AND environment = ${environment}\n `);\n\n if (data.length === 0) {\n throw new Error(\n `Env config not found: ${a.appName}/${a.environment}${a.releaseProfile ? ` (profile: ${a.releaseProfile})` : \"\"}`,\n );\n }\n if (data.length > 1) {\n const stageIds = data\n .map((r) => r.release_profile_stage_id)\n .filter((v): v is string => Boolean(v));\n const profileNames = await getProfileNamesForStageIds(stageIds);\n const names = [...new Set(Object.values(profileNames))].join(\", \");\n throw new Error(\n `Multiple env configs found for ${a.appName}/${a.environment} across profiles: ${names}. ` +\n `Pass releaseProfile parameter to select one (e.g. releaseProfile: \"${Object.values(profileNames)[0] || \"...\"}\")`,\n );\n }\n\n const decrypted = decrypt(data[0]!.env_data_encrypted);\n return { content: [{ type: \"text\", text: decrypted }] };\n }\n\n case \"env-store\": {\n const appName = String(a.appName);\n const environment = String(a.environment);\n const encrypted = encrypt(String(a.content));\n\n let resolvedStageIds: string[] | null = null;\n if (a.releaseProfile) {\n const { stageIds } = await resolveReleaseProfileStageIds(\n String(a.releaseProfile),\n );\n resolvedStageIds = stageIds;\n }\n\n interface ExistingEnvConfigRow extends Record<string, unknown> {\n id: string;\n release_profile_stage_id: string | null;\n }\n const existingRows = resolvedStageIds\n ? await db.execute<ExistingEnvConfigRow>(sql`\n SELECT id, release_profile_stage_id\n FROM env_config\n WHERE app_name = ${appName}\n AND environment = ${environment}\n AND release_profile_stage_id = ANY(${uuidArrayParam(resolvedStageIds)})\n `)\n : await db.execute<ExistingEnvConfigRow>(sql`\n SELECT id, release_profile_stage_id\n FROM env_config\n WHERE app_name = ${appName}\n AND environment = ${environment}\n `);\n\n if (existingRows.length > 1 && !resolvedStageIds) {\n const stageIds = existingRows\n .map((r) => r.release_profile_stage_id)\n .filter((v): v is string => Boolean(v));\n const profileNames = await getProfileNamesForStageIds(stageIds);\n const names = [...new Set(Object.values(profileNames))].join(\", \");\n throw new Error(\n `Multiple env configs found for ${appName}/${environment} across profiles: ${names}. ` +\n `Pass releaseProfile parameter to select one.`,\n );\n }\n\n const existing = existingRows[0] ?? null;\n const description = a.description ? String(a.description) : null;\n const updatedBy = authContext!.userId;\n let saveMsg: string;\n if (existing) {\n await db.execute(sql`\n UPDATE env_config\n SET env_data_encrypted = ${encrypted},\n description = COALESCE(${description}, description),\n updated_by = ${updatedBy},\n updated_at = ${new Date().toISOString()}\n WHERE id = ${existing.id}\n `);\n saveMsg = `Updated env config: ${appName}/${environment}`;\n } else {\n const stageId = resolvedStageIds?.[0] ?? null;\n await db.execute(sql`\n INSERT INTO env_config (\n app_name, environment, env_data_encrypted, description,\n created_by, updated_by, release_profile_stage_id\n ) VALUES (\n ${appName},\n ${environment},\n ${encrypted},\n ${description},\n ${updatedBy},\n ${updatedBy},\n ${stageId}\n )\n `);\n saveMsg = `Stored env config: ${appName}/${environment}`;\n }\n\n // Vercel push pipeline removed in 6.5.0 — env vars only land in\n // the local mg-dashboard env_config table here. Push to Vercel\n // (or any other deploy target) happens on demand via the\n // dashboard UI, which still uses the resolved stage link.\n return { content: [{ type: \"text\", text: saveMsg }] };\n }\n\n // ----- Cache Purge -----\n case \"cache-purge\": {\n const { conn, proxy } = await getServerConnection(String(a.serverId));\n conn.timeout = 120_000;\n const script = `\nR=\"\"\n# 1. OPcache – kill lsphp so it respawns with a fresh OPcache\nif pgrep -x lsphp >/dev/null 2>&1; then\n sudo killall lsphp 2>/dev/null && R=\"\\${R}[OK] OPcache: killed lsphp processes\\\\n\" || R=\"\\${R}[FAIL] OPcache: could not kill lsphp\\\\n\"\nelse\n R=\"\\${R}[SKIP] OPcache: no lsphp processes running\\\\n\"\nfi\n# 2. LiteSpeed cache directories\nLS=0\nfor cdir in /tmp/lshttpd/swap /usr/local/lsws/cachedata; do\n if [ -d \"\\$cdir\" ] && [ \"\\$(ls -A \"\\$cdir\" 2>/dev/null)\" ]; then\n sudo rm -rf \"\\$cdir\"/* 2>/dev/null && R=\"\\${R}[OK] LS cache: cleared \\$cdir\\\\n\" && LS=1 || R=\"\\${R}[FAIL] LS cache: \\$cdir\\\\n\"\n fi\ndone\n[ \"\\$LS\" -eq 0 ] && R=\"\\${R}[SKIP] LS cache: no cache dirs with content\\\\n\"\n# 3. LiteSpeed graceful restart\nif [ -x /usr/local/lsws/bin/lswsctrl ]; then\n sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R=\"\\${R}[OK] LiteSpeed: graceful restart\\\\n\" || R=\"\\${R}[FAIL] LiteSpeed: restart failed\\\\n\"\nelif systemctl is-active lsws >/dev/null 2>&1 || systemctl is-active lshttpd >/dev/null 2>&1; then\n sudo systemctl restart lsws 2>/dev/null || sudo systemctl restart lshttpd 2>/dev/null\n R=\"\\${R}[OK] LiteSpeed: restarted via systemctl\\\\n\"\nelse\n R=\"\\${R}[SKIP] LiteSpeed: not detected\\\\n\"\nfi\n# 4. WordPress caches\nWP=0\nfor dir in /var/www/*/; do\n [ -d \"\\$dir\" ] || continue\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\n [ -f \"\\$root/wp-config.php\" ] || continue\n WP=1; SITE=\\$(basename \"\\$dir\")\n if command -v wp >/dev/null 2>&1; then\n wp cache flush --allow-root --path=\"\\$root\" 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): wp cache flush\\\\n\" || R=\"\\${R}[FAIL] WP (\\$SITE): wp cache flush\\\\n\"\n elif [ -d \"\\$root/wp-content/cache\" ]; then\n rm -rf \"\\$root/wp-content/cache\"/* 2>/dev/null && R=\"\\${R}[OK] WP (\\$SITE): cleared wp-content/cache\\\\n\"\n else\n R=\"\\${R}[SKIP] WP (\\$SITE): no cache dir, no wp-cli\\\\n\"\n fi\n break\n done\ndone\n[ \"\\$WP\" -eq 0 ] && R=\"\\${R}[SKIP] WordPress: no sites found\\\\n\"\n# 5. PrestaShop caches\nPS=0\nfor dir in /var/www/*/; do\n [ -d \"\\$dir\" ] || continue\n for root in \"\\$dir\" \"\\${dir}html\" \"\\${dir}public_html\" \"\\${dir}public\" \"\\${dir}httpdocs\"; do\n IS=0\n [ -f \"\\$root/app/config/parameters.php\" ] && IS=1\n [ -f \"\\$root/config/settings.inc.php\" ] && IS=1\n [ \"\\$IS\" -eq 0 ] && continue\n PS=1; SITE=\\$(basename \"\\$dir\"); C=\"\"\n [ -d \"\\$root/var/cache\" ] && rm -rf \"\\$root/var/cache\"/* 2>/dev/null && C=\"\\${C}var/cache \"\n [ -d \"\\$root/cache/smarty/compile\" ] && rm -rf \"\\$root/cache/smarty/compile\"/* 2>/dev/null && C=\"\\${C}smarty/compile \"\n [ -d \"\\$root/cache/smarty/cache\" ] && rm -rf \"\\$root/cache/smarty/cache\"/* 2>/dev/null && C=\"\\${C}smarty/cache \"\n [ -n \"\\$C\" ] && R=\"\\${R}[OK] PS (\\$SITE): cleared \\${C}\\\\n\" || R=\"\\${R}[SKIP] PS (\\$SITE): no cache dirs\\\\n\"\n break\n done\ndone\n[ \"\\$PS\" -eq 0 ] && R=\"\\${R}[SKIP] PrestaShop: no sites found\\\\n\"\n# 6. Redis\nif command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then\n redis-cli FLUSHALL 2>/dev/null && R=\"\\${R}[OK] Redis: FLUSHALL\\\\n\" || R=\"\\${R}[FAIL] Redis: FLUSHALL failed\\\\n\"\nelse\n R=\"\\${R}[SKIP] Redis: not available\\\\n\"\nfi\n# 7. Memcached\nif systemctl is-active memcached >/dev/null 2>&1; then\n if command -v memcflush >/dev/null 2>&1; then\n memcflush --servers=localhost 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\n else\n echo \"flush_all\" | nc -q1 localhost 11211 2>/dev/null && R=\"\\${R}[OK] Memcached: flushed via nc\\\\n\" || R=\"\\${R}[FAIL] Memcached: flush failed\\\\n\"\n fi\nelse\n R=\"\\${R}[SKIP] Memcached: not active\\\\n\"\nfi\necho -e \"\\$R\"\n`.trim();\n const result = await sshExec(conn, script, proxy);\n const output = (result.stdout || \"\").trim();\n return {\n content: [\n {\n type: \"text\",\n text: output || \"Cache purge completed (no output)\",\n },\n ],\n };\n }\n\n // ----- Domains (mijn.host) -----\n case \"domain-list\": {\n interface DomainListItem {\n id: number;\n domain: string;\n renewal_date: string;\n status: string;\n status_id: number;\n tags: string[];\n }\n\n const res = await mijnhostFetch<{ domains: DomainListItem[] }>(\n \"/domains\",\n );\n const domains = res.data.domains;\n\n if (!domains.length) {\n return { content: [{ type: \"text\", text: \"No domains found\" }] };\n }\n\n const details = a.details === true;\n if (!details) {\n const lines = domains.map((d) => {\n const tags = d.tags?.length ? ` [${d.tags.join(\", \")}]` : \"\";\n return `${d.domain} status=${d.status} renewal=${d.renewal_date}${tags}`;\n });\n return {\n content: [\n {\n type: \"text\",\n text: `${domains.length} domain(s):\\n\\n${lines.join(\"\\n\")}`,\n },\n ],\n };\n }\n\n // details: true → fetch DNS zone per active domain in parallel and\n // summarise NS / MX / SPF / DMARC. Inactive domains are skipped so\n // we don't burn API quota on records that don't exist.\n interface DnsRec {\n type: string;\n name: string;\n value: string;\n ttl: number;\n }\n const concurrency = Math.min(\n Math.max(Number(a.concurrency) || 8, 1),\n 20,\n );\n\n type Summary = {\n mx: string[];\n hasSpf: boolean;\n hasDmarc: boolean;\n error?: string;\n };\n const summaries = new Map<string, Summary>();\n\n const skipStatuses = new Set([\n \"expired\",\n \"redemptionperiod\",\n \"pendingdelete\",\n \"inactive\",\n ]);\n const activeDomains = domains.filter(\n (d) => !skipStatuses.has((d.status || \"\").toLowerCase()),\n );\n\n async function fetchSummary(domain: string): Promise<Summary> {\n try {\n const r = await mijnhostFetch<{ records: DnsRec[] }>(\n `/domains/${encodeURIComponent(domain)}/dns`,\n );\n const recs = r.data.records || [];\n // mijn.host's /dns endpoint exposes records inside the zone but\n // not the zone's own NS delegation, so we deliberately don't\n // report nameservers here (was misleading \"(none)\" for every row).\n const mx = recs\n .filter((x) => x.type === \"MX\")\n .map((x) => x.value)\n .sort();\n const hasSpf = recs.some(\n (x) =>\n x.type === \"TXT\" && x.value.toLowerCase().includes(\"v=spf1\"),\n );\n const hasDmarc = recs.some(\n (x) =>\n x.type === \"TXT\" &&\n (x.name.toLowerCase().startsWith(\"_dmarc\") ||\n x.value.toLowerCase().includes(\"v=dmarc1\")),\n );\n return { mx, hasSpf, hasDmarc };\n } catch (err) {\n return {\n mx: [],\n hasSpf: false,\n hasDmarc: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n // Simple parallel pool — keeps `concurrency` requests in flight.\n const queue = [...activeDomains];\n async function worker() {\n while (queue.length > 0) {\n const d = queue.shift();\n if (!d) return;\n summaries.set(d.domain, await fetchSummary(d.domain));\n }\n }\n await Promise.all(\n Array.from({ length: Math.min(concurrency, queue.length) }, worker),\n );\n\n const lines = domains.map((d) => {\n const tags = d.tags?.length ? ` [${d.tags.join(\", \")}]` : \"\";\n const head = `${d.domain} status=${d.status} expires=${d.renewal_date}${tags}`;\n const s = summaries.get(d.domain);\n if (!s) return head;\n if (s.error) return `${head}\\n dns: error: ${s.error}`;\n const mx = s.mx.length ? s.mx.join(\", \") : \"(none)\";\n return `${head}\\n mx=${mx} spf=${s.hasSpf ? \"yes\" : \"NO\"} dmarc=${s.hasDmarc ? \"yes\" : \"NO\"}`;\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: `${domains.length} domain(s) (${activeDomains.length} with DNS lookup):\\n\\n${lines.join(\"\\n\")}`,\n },\n ],\n };\n }\n\n case \"dns-list\": {\n const domain = String(a.domain);\n if (!domain) throw new Error(\"domain is required\");\n\n interface DnsRecord {\n type: string;\n name: string;\n value: string;\n ttl: number;\n }\n\n const res = await mijnhostFetch<{\n domain: string;\n records: DnsRecord[];\n }>(`/domains/${encodeURIComponent(domain)}/dns`);\n const records = res.data.records;\n\n if (!records.length) {\n return {\n content: [\n { type: \"text\", text: `No DNS records found for ${domain}` },\n ],\n };\n }\n\n const header =\n \"TYPE NAME VALUE TTL\";\n const sep = \"-\".repeat(90);\n const lines = records.map(\n (r) =>\n `${r.type.padEnd(10)}${r.name.padEnd(31)}${r.value.substring(0, 40).padEnd(41)}${r.ttl}`,\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: `DNS records for ${domain} (${records.length}):\\n\\n${header}\\n${sep}\\n${lines.join(\"\\n\")}`,\n },\n ],\n };\n }\n\n case \"dns-record\": {\n const action = String(a.action);\n if (action !== \"create\" && action !== \"update\" && action !== \"delete\") {\n throw new Error(\"action must be one of: create, update, delete\");\n }\n\n const domain = String(a.domain);\n const type = String(a.type).toUpperCase();\n const dnsName = String(a.name);\n const dryRun = a.dryRun === true;\n\n if (!domain || !type || !dnsName) {\n throw new Error(\"domain, type, and name are required\");\n }\n\n interface DnsRecord {\n type: string;\n name: string;\n value: string;\n ttl: number;\n }\n\n // Serialize per-domain so concurrent mutations can't race on the\n // GET-then-PUT-whole-zone semantics that mijn.host enforces. Inside\n // the lock we re-fetch the zone, build the next state, PUT it, and\n // record the timestamp so the next call paces itself.\n return withDnsZoneLock(domain, async () => {\n const fetchZone = () =>\n mijnhostFetch<{ domain: string; records: DnsRecord[] }>(\n `/domains/${encodeURIComponent(domain)}/dns`,\n );\n\n // mijn.host occasionally returns a stale/empty zone snapshot when\n // followed by a PUT it wants us to back off from. Detect that by\n // requiring at least one record in the zone (we know all of these\n // domains have at least the SOA-derived records); if the first GET\n // looks suspiciously empty, retry once after a short delay.\n let current = await fetchZone();\n if (current.data.records.length === 0) {\n await sleep(DNS_RETRY_BACKOFF_MS);\n current = await fetchZone();\n }\n\n let nextRecords: DnsRecord[];\n let diffArgs: {\n verb: \"create\" | \"update\" | \"delete\";\n added?: DnsRecord[];\n removed?: DnsRecord[];\n };\n let okMessage: string;\n\n if (action === \"create\") {\n const value = typeof a.value === \"string\" ? a.value : \"\";\n if (!value) throw new Error('action=\"create\" requires value');\n const ttl = Number(a.ttl) || 3600;\n const newRecord: DnsRecord = { type, name: dnsName, value, ttl };\n nextRecords = [...current.data.records, newRecord];\n diffArgs = { verb: \"create\", added: [newRecord] };\n okMessage = `DNS record created: ${type} ${dnsName} → ${value} (TTL: ${ttl})`;\n } else if (action === \"update\") {\n const oldValue = typeof a.oldValue === \"string\" ? a.oldValue : \"\";\n const newValue = typeof a.newValue === \"string\" ? a.newValue : \"\";\n if (!oldValue || !newValue)\n throw new Error('action=\"update\" requires oldValue and newValue');\n const ttlArg = a.ttl !== undefined ? Number(a.ttl) : undefined;\n\n const idx = current.data.records.findIndex(\n (r) =>\n r.type === type && r.name === dnsName && r.value === oldValue,\n );\n if (idx === -1) {\n throw new Error(\n `No matching DNS record found: ${type} ${dnsName} = ${oldValue}\\n` +\n describeDnsCandidates(\n current.data.records,\n type,\n dnsName,\n oldValue,\n ),\n );\n }\n\n const updated = [...current.data.records];\n const before = updated[idx]!;\n const after: DnsRecord = {\n type,\n name: dnsName,\n value: newValue,\n ttl: ttlArg ?? before.ttl,\n };\n updated[idx] = after;\n nextRecords = updated;\n diffArgs = { verb: \"update\", removed: [before], added: [after] };\n okMessage = `DNS record updated: ${type} ${dnsName} → ${newValue}${ttlArg ? ` (TTL: ${ttlArg})` : \"\"}`;\n } else {\n const value = typeof a.value === \"string\" ? a.value : \"\";\n if (!value) throw new Error('action=\"delete\" requires value');\n\n const removed = current.data.records.filter(\n (r) => r.type === type && r.name === dnsName && r.value === value,\n );\n const remaining = current.data.records.filter(\n (r) =>\n !(r.type === type && r.name === dnsName && r.value === value),\n );\n if (removed.length === 0) {\n throw new Error(\n `No matching DNS record found: ${type} ${dnsName} = ${value}\\n` +\n describeDnsCandidates(\n current.data.records,\n type,\n dnsName,\n value,\n ),\n );\n }\n nextRecords = remaining;\n diffArgs = { verb: \"delete\", removed };\n okMessage = `DNS record deleted: ${type} ${dnsName} = ${value} (${remaining.length} records remaining)`;\n }\n\n if (dryRun) {\n const diff = formatDnsDiff(\n domain,\n current.data.records,\n nextRecords,\n diffArgs,\n );\n return { content: [{ type: \"text\", text: diff }] };\n }\n\n // Refuse to PUT a near-empty zone unless that is clearly the user's\n // intent (i.e. we're explicitly deleting down to that). This is the\n // last line of defense against a stale GET wiping the zone.\n if (\n nextRecords.length < 3 &&\n current.data.records.length >= 5 &&\n action !== \"delete\"\n ) {\n throw new Error(\n `Aborting PUT: would shrink ${domain} from ${current.data.records.length} to ${nextRecords.length} records. ` +\n \"This usually indicates a stale zone snapshot from mijn.host. Run dns-list and retry.\",\n );\n }\n\n try {\n await mijnhostFetch<void>(\n `/domains/${encodeURIComponent(domain)}/dns`,\n {\n method: \"PUT\",\n body: JSON.stringify({ records: nextRecords }),\n },\n );\n } catch (err) {\n if (!isTransientMijnhostError(err)) throw err;\n // One retry against a freshly fetched zone — the previous failure\n // may itself have applied (mijn.host returns 500 on consistency\n // hiccups even after a successful write), so we rebuild the diff.\n await sleep(DNS_RETRY_BACKOFF_MS);\n const refetched = await fetchZone();\n const stillNeedsApply =\n action === \"create\"\n ? !refetched.data.records.some(\n (r) =>\n r.type === type &&\n r.name === dnsName &&\n r.value === (typeof a.value === \"string\" ? a.value : \"\"),\n )\n : true;\n if (!stillNeedsApply) {\n markDnsPut(domain);\n return {\n content: [\n {\n type: \"text\",\n text: `${okMessage} (already applied; recovered from transient error)`,\n },\n ],\n };\n }\n await mijnhostFetch<void>(\n `/domains/${encodeURIComponent(domain)}/dns`,\n {\n method: \"PUT\",\n body: JSON.stringify({ records: nextRecords }),\n },\n );\n }\n\n markDnsPut(domain);\n return { content: [{ type: \"text\", text: okMessage }] };\n });\n }\n\n default:\n if (TRIGGER_TOOL_NAMES.has(name)) {\n return handleTriggerTool(name, a, { sshExec, getServerConnection });\n }\n if (REPO_TOOL_NAMES.has(name)) {\n return handleRepoTool(name, a, { db, sshExec, getServerConnection });\n }\n return { content: [{ type: \"text\", text: `Unknown tool: ${name}` }] };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { content: [{ type: \"text\", text: `Error: ${message}` }] };\n }\n}\n\n/** Create a configured MCP Server instance with handlers attached. */\nfunction createMcpServer(): Server {\n const s = new Server(\n { name: \"mg-dashboard-mcp\", version: MCP_VERSION },\n { capabilities: { tools: {} } },\n );\n s.setRequestHandler(ListToolsRequestSchema, handleListTools);\n s.setRequestHandler(\n CallToolRequestSchema,\n handleCallTool as Parameters<typeof s.setRequestHandler>[1],\n );\n return s;\n}\n\nconst server = createMcpServer();\n\n// ---------------------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------------------\n\nasync function main() {\n console.error(\"Starting MG Dashboard MCP Server...\");\n\n const apiAuthContext = await validateApiKey(apiKey!);\n if (!apiAuthContext) {\n console.error(\"API key validation failed\");\n process.exit(1);\n }\n\n authContext = await validateSshKey(sshKeyPath!, apiAuthContext.apiKeyId);\n if (!authContext) {\n console.error(\"SSH-key authentication failed\");\n process.exit(1);\n }\n\n console.error(\n `[Security] MCP v${MCP_VERSION} | Key: ${authContext.apiKeyName}`,\n );\n\n const toolNames = TOOLS.map((t) => t.name).join(\", \");\n\n if (httpMode) {\n console.error(\n `API key validated. Starting Streamable HTTP transport on port ${httpPort}...`,\n );\n\n const transports = new Map<string, StreamableHTTPServerTransport>();\n\n const httpServer = createHttpServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", `http://localhost:${httpPort}`);\n\n if (url.pathname !== \"/mcp\") {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n return;\n }\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204, {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, mcp-session-id\",\n \"Access-Control-Expose-Headers\": \"mcp-session-id\",\n });\n res.end();\n return;\n }\n\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Expose-Headers\", \"mcp-session-id\");\n\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n\n let body: Record<string, unknown> | undefined;\n if (req.method === \"POST\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n try {\n body = JSON.parse(Buffer.concat(chunks).toString());\n } catch {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Invalid JSON\");\n return;\n }\n }\n\n if (sessionId && transports.has(sessionId)) {\n await transports.get(sessionId)!.handleRequest(req, res, body);\n return;\n }\n\n if (\n req.method === \"POST\" &&\n body &&\n (Array.isArray(body)\n ? body.some(isInitializeRequest)\n : isInitializeRequest(body))\n ) {\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n });\n transport.onclose = () => {\n if (transport.sessionId) transports.delete(transport.sessionId);\n };\n const sessionServer = createMcpServer();\n await sessionServer.connect(transport);\n if (transport.sessionId) transports.set(transport.sessionId, transport);\n await transport.handleRequest(req, res, body);\n return;\n }\n\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Bad request — missing or invalid session\");\n });\n\n httpServer.listen(httpPort, () => {\n console.error(\n `MCP HTTP server ready on port ${httpPort}. Tools: ${toolNames}`,\n );\n });\n } else {\n console.error(\"API key validated. Starting stdio transport...\");\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(`MCP Server ready. Tools: ${toolNames}`);\n }\n}\n\nmain().catch((err) => {\n console.error(\"Fatal error:\", err);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/proxy-mode.ts","../src/db-ssh-tunnel.ts","../src/trigger-tools.ts","../../../node_modules/server-only/index.js"],"names":["args","proxyUrl","apiKey","expandHome","join","existsSync","connectSsh","SshClient","readFileSync","server"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Proxy-mode entry point for the MG dashboard MCP package.\r\n *\r\n * Usage:\r\n * npx @mgsoftwarebv/mg-dashboard-mcp \\\r\n * --proxy-url=https://mg-mcp.mgsoftware.nl/v1/{INSTANCE_ID}/mcp \\\r\n * --api-key=pk_xxx \\\r\n * --ssh-key=$HOME/.ssh/id_ed25519\r\n *\r\n * What it does:\r\n * 1. At startup it does an SSH-key challenge handshake against the proxy\r\n * (POST /v1/auth/ssh/challenge → ssh-keygen -Y sign → POST\r\n * /v1/auth/ssh/verify) and obtains a short-lived `pks_xxx` bearer.\r\n * 2. It then runs as a stdio MCP server, transparently forwarding every\r\n * JSON-RPC message to/from the upstream proxy URL using\r\n * `StreamableHTTPClientTransport` with the bearer attached.\r\n * 3. Before the token expires it re-runs the handshake and swaps in the\r\n * fresh bearer without dropping the connection.\r\n *\r\n * This lets a user point Cursor's mcp.json at the local stdio command with\r\n * both factors: a static `pk_` proxy key plus a linked SSH key proof. The\r\n * static key is only sent during the SSH verify step; normal MCP traffic uses\r\n * the short-lived `pks_` session token.\r\n */\r\n\r\nimport { spawn } from \"node:child_process\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\r\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\r\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\r\nimport {\r\n CallToolRequestSchema,\r\n CallToolResultSchema,\r\n EmptyResultSchema,\r\n GetPromptRequestSchema,\r\n GetPromptResultSchema,\r\n ListPromptsRequestSchema,\r\n ListPromptsResultSchema,\r\n ListResourcesRequestSchema,\r\n ListResourcesResultSchema,\r\n ListResourceTemplatesRequestSchema,\r\n ListResourceTemplatesResultSchema,\r\n ListToolsRequestSchema,\r\n ListToolsResultSchema,\r\n ReadResourceRequestSchema,\r\n ReadResourceResultSchema,\r\n SubscribeRequestSchema,\r\n UnsubscribeRequestSchema,\r\n} from \"@modelcontextprotocol/sdk/types.js\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// CLI helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction getArg(args: string[], name: string): string | undefined {\r\n return args.find((a) => a.startsWith(`--${name}=`))?.split(\"=\").slice(1).join(\"=\");\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePubkeyPath(input: string): { pubPath: string; pubText: string } {\r\n const candidate = expandHome(input);\r\n let pubPath: string;\r\n if (candidate.endsWith(\".pub\")) {\r\n pubPath = candidate;\r\n } else if (existsSync(`${candidate}.pub`)) {\r\n pubPath = `${candidate}.pub`;\r\n } else if (existsSync(candidate)) {\r\n pubPath = candidate;\r\n } else {\r\n throw new Error(`SSH key file not found: ${candidate} (also tried ${candidate}.pub)`);\r\n }\r\n const pubText = readFileSync(pubPath, \"utf8\").trim();\r\n if (!pubText) throw new Error(`SSH public-key file is empty: ${pubPath}`);\r\n return { pubPath, pubText };\r\n}\r\n\r\nfunction runProcess(\r\n command: string,\r\n argv: string[],\r\n options: { stdin?: string } = {},\r\n): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve) => {\r\n const child = spawn(command, argv, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n child.stdout.on(\"data\", (d) => {\r\n stdout += d.toString();\r\n });\r\n child.stderr.on(\"data\", (d) => {\r\n stderr += d.toString();\r\n });\r\n child.on(\"error\", (err) => {\r\n resolve({ stdout, stderr: stderr + String(err), code: -1 });\r\n });\r\n child.on(\"close\", (code) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n if (options.stdin !== undefined) {\r\n child.stdin.write(options.stdin);\r\n child.stdin.end();\r\n } else {\r\n child.stdin.end();\r\n }\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH-key handshake against /v1/auth/ssh/challenge + /v1/auth/ssh/verify\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface HandshakeResult {\r\n token: string;\r\n expiresAt: number; // ms epoch\r\n proxyKeyName: string;\r\n}\r\n\r\nfunction deriveAuthBaseUrl(proxyUrl: string): string {\r\n // proxyUrl looks like https://host/v1/{instanceId}/mcp\r\n // We need to call https://host (base) then /v1/auth/ssh/{challenge|verify}.\r\n const u = new URL(proxyUrl);\r\n return `${u.protocol}//${u.host}`;\r\n}\r\n\r\nasync function performHandshake(\r\n proxyUrl: string,\r\n apiKey: string,\r\n pubPath: string,\r\n pubText: string,\r\n): Promise<HandshakeResult> {\r\n const base = deriveAuthBaseUrl(proxyUrl);\r\n\r\n const challengeRes = await fetch(`${base}/v1/auth/ssh/challenge`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: \"{}\",\r\n });\r\n if (!challengeRes.ok) {\r\n const txt = await challengeRes.text().catch(() => \"\");\r\n throw new Error(`Challenge request failed (${challengeRes.status}): ${txt}`);\r\n }\r\n const challenge = (await challengeRes.json()) as {\r\n challenge_id: string;\r\n nonce: string;\r\n namespace: string;\r\n };\r\n\r\n const sign = await runProcess(\r\n \"ssh-keygen\",\r\n [\"-Y\", \"sign\", \"-f\", pubPath, \"-n\", challenge.namespace, \"-q\"],\r\n { stdin: challenge.nonce },\r\n );\r\n if (sign.code !== 0 || !sign.stdout.includes(\"BEGIN SSH SIGNATURE\")) {\r\n throw new Error(\r\n `ssh-keygen sign failed (exit ${sign.code}). Make sure ssh-agent is running ` +\r\n `and has the matching private key loaded. stderr: ${sign.stderr.trim() || \"(empty)\"}`,\r\n );\r\n }\r\n\r\n const verifyRes = await fetch(`${base}/v1/auth/ssh/verify`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n challenge_id: challenge.challenge_id,\r\n api_key: apiKey,\r\n pubkey: pubText,\r\n signature: sign.stdout,\r\n }),\r\n });\r\n if (!verifyRes.ok) {\r\n const txt = await verifyRes.text().catch(() => \"\");\r\n throw new Error(`Verify request failed (${verifyRes.status}): ${txt}`);\r\n }\r\n const verified = (await verifyRes.json()) as {\r\n token: string;\r\n expires_in_seconds: number;\r\n proxy_key_name: string;\r\n };\r\n\r\n return {\r\n token: verified.token,\r\n expiresAt: Date.now() + verified.expires_in_seconds * 1000,\r\n proxyKeyName: verified.proxy_key_name,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Bidirectional message forwarding\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Bridge between a stdio MCP server (talking to e.g. Cursor) and a remote\r\n * Streamable-HTTP MCP server (the proxy). Each incoming JSON-RPC message\r\n * is forwarded verbatim, and responses / notifications stream back.\r\n */\r\nasync function runBridge(handshake: HandshakeResult, proxyUrl: string, refresh: () => Promise<HandshakeResult>) {\r\n let currentToken = handshake.token;\r\n const requestHeaders: Record<string, string> = {\r\n Authorization: `Bearer ${currentToken}`,\r\n };\r\n\r\n const upstreamTransport = new StreamableHTTPClientTransport(new URL(proxyUrl), {\r\n requestInit: { headers: requestHeaders },\r\n });\r\n const upstream = new Client({ name: \"mg-dashboard-mcp-proxy-bridge\", version: \"1.0.0\" });\r\n\r\n // Schedule a refresh 2 minutes before expiry.\r\n const scheduleRefresh = (result: HandshakeResult) => {\r\n const msUntilRefresh = Math.max(30_000, result.expiresAt - Date.now() - 120_000);\r\n setTimeout(async () => {\r\n try {\r\n const fresh = await refresh();\r\n currentToken = fresh.token;\r\n requestHeaders.Authorization = `Bearer ${currentToken}`;\r\n console.error(`[Proxy] Token refreshed (key: ${fresh.proxyKeyName})`);\r\n scheduleRefresh(fresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Token refresh failed: ${err instanceof Error ? err.message : String(err)}`);\r\n // Try again sooner on failure.\r\n setTimeout(() => scheduleRefresh({ ...result, expiresAt: Date.now() + 60_000 }), 30_000);\r\n }\r\n }, msUntilRefresh).unref();\r\n };\r\n scheduleRefresh(handshake);\r\n\r\n // Server-side stdio transport faces Cursor.\r\n const stdioServer = new Server(\r\n { name: \"mg-dashboard-mcp-proxy\", version: \"1.0.0\" },\r\n { capabilities: { tools: {}, prompts: {}, resources: {}, logging: {} } },\r\n );\r\n\r\n const forwardRequest =\r\n (resultSchema: Parameters<typeof upstream.request>[1]) =>\r\n async (request: unknown) =>\r\n upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n resultSchema,\r\n );\r\n\r\n // Explicitly forward first-class MCP methods. The SDK fallback only covers\r\n // truly unknown methods; Cursor's standard discovery calls need registered\r\n // handlers or the client sees an empty server.\r\n stdioServer.setRequestHandler(\r\n ListToolsRequestSchema,\r\n forwardRequest(ListToolsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n CallToolRequestSchema,\r\n forwardRequest(CallToolResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListPromptsRequestSchema,\r\n forwardRequest(ListPromptsResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n GetPromptRequestSchema,\r\n forwardRequest(GetPromptResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourcesRequestSchema,\r\n forwardRequest(ListResourcesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ReadResourceRequestSchema,\r\n forwardRequest(ReadResourceResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n ListResourceTemplatesRequestSchema,\r\n forwardRequest(ListResourceTemplatesResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n SubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n stdioServer.setRequestHandler(\r\n UnsubscribeRequestSchema,\r\n forwardRequest(EmptyResultSchema) as Parameters<typeof stdioServer.setRequestHandler>[1],\r\n );\r\n\r\n // Dumb forwarder: any request from Cursor → forward to upstream → return result.\r\n stdioServer.fallbackRequestHandler = async (request: unknown) => {\r\n return await upstream.request(\r\n request as Parameters<typeof upstream.request>[0],\r\n // We don't care about the schema check on the way through — let the\r\n // upstream's actual response flow back unmodified.\r\n undefined as unknown as Parameters<typeof upstream.request>[1],\r\n );\r\n };\r\n // Same for notifications.\r\n stdioServer.fallbackNotificationHandler = async (notification: unknown) => {\r\n await upstream.notification(notification as Parameters<typeof upstream.notification>[0]);\r\n };\r\n\r\n await upstream.connect(upstreamTransport);\r\n\r\n // Forward upstream notifications back to Cursor.\r\n upstream.fallbackNotificationHandler = async (notification: unknown) => {\r\n await stdioServer.notification(notification as Parameters<typeof stdioServer.notification>[0]);\r\n };\r\n\r\n await stdioServer.connect(new StdioServerTransport());\r\n console.error(`[Proxy] Bridge ready. Forwarding stdio → ${proxyUrl}`);\r\n\r\n // In proxy mode this function is the long-lived process. Some SDK transports\r\n // finish their async `connect()` setup without leaving an obvious foreground\r\n // handle behind, which can make Node exit immediately after \"Bridge ready\".\r\n // Keep the process alive until Cursor closes stdin or the process receives a\r\n // termination signal.\r\n await new Promise<void>((resolve) => {\r\n const keepAlive = setInterval(() => undefined, 2_147_483_647);\r\n const done = () => {\r\n clearInterval(keepAlive);\r\n resolve();\r\n };\r\n process.stdin.once(\"close\", done);\r\n process.stdin.once(\"end\", done);\r\n process.once(\"SIGINT\", done);\r\n process.once(\"SIGTERM\", done);\r\n });\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nexport async function runProxyMode(args: string[]): Promise<void> {\r\n const proxyUrl = getArg(args, \"proxy-url\") || process.env.MG_DASHBOARD_PROXY_URL;\r\n const apiKey = getArg(args, \"api-key\") || process.env.MG_DASHBOARD_API_KEY;\r\n const sshKey = getArg(args, \"ssh-key\") || process.env.MG_DASHBOARD_SSH_KEY;\r\n\r\n if (!proxyUrl) {\r\n console.error(\"--proxy-url is required (or set MG_DASHBOARD_PROXY_URL)\");\r\n process.exit(1);\r\n }\r\n if (!apiKey) {\r\n console.error(\"--api-key is required in proxy mode (or set MG_DASHBOARD_API_KEY)\");\r\n process.exit(1);\r\n }\r\n if (!sshKey) {\r\n console.error(\"--ssh-key is required in proxy mode (or set MG_DASHBOARD_SSH_KEY)\");\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Starting in proxy-bridge mode → ${proxyUrl}`);\r\n\r\n let resolved: { pubPath: string; pubText: string };\r\n try {\r\n resolved = resolvePubkeyPath(sshKey);\r\n } catch (err) {\r\n console.error(`[Proxy] ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n const refresh = () => performHandshake(proxyUrl, apiKey, resolved.pubPath, resolved.pubText);\r\n\r\n let handshake: HandshakeResult;\r\n try {\r\n handshake = await refresh();\r\n } catch (err) {\r\n console.error(`[Proxy] Handshake failed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`[Proxy] Authenticated as \"${handshake.proxyKeyName}\"`);\r\n console.error(`[Proxy] Token valid for ${Math.floor((handshake.expiresAt - Date.now()) / 60000)} min`);\r\n\r\n try {\r\n await runBridge(handshake, proxyUrl, refresh);\r\n } catch (err) {\r\n console.error(`[Proxy] Bridge crashed: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n}\r\n","/**\r\n * Opens an SSH-key-authenticated TCP forward to the remote Postgres host and\r\n * rewrites the database URL to hit the local listener. Used when the production\r\n * Postgres port is firewalled and only reachable from inside the host that the\r\n * MCP user already has SSH access to.\r\n *\r\n * Reuses the same SSH key the MCP already uses for proxy-mode auth, so the\r\n * trust model is unchanged: holding the key = ability to reach the DB.\r\n */\r\n\r\nimport { createServer, type AddressInfo, type Server, type Socket } from \"node:net\";\r\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\nimport { Client as SshClient, type ClientChannel } from \"ssh2\";\r\n\r\nexport interface DbSshTunnelOptions {\r\n /** \"user@host[:port]\" target for the SSH connection. */\r\n sshTarget: string;\r\n /** Path to the SSH private key (or its `.pub`; we'll find the private one). */\r\n sshKeyPath: string;\r\n /** Original Postgres URL (host/port get rewritten to the local listener). */\r\n databaseUrl: string;\r\n /** Optional override for the SSH keepalive interval (ms). Default 30s. */\r\n keepaliveIntervalMs?: number;\r\n /** When true (default), exit the process if the SSH session closes (MCP respawn). */\r\n exitProcessOnSshClose?: boolean;\r\n}\r\n\r\nexport interface DbSshTunnel {\r\n /** New URL pointing at 127.0.0.1:<localPort>, same path/credentials/query. */\r\n rewrittenDatabaseUrl: string;\r\n /** Local TCP port the rewritten URL points at. */\r\n localPort: number;\r\n /** Closes the tunnel and SSH connection. */\r\n close(): Promise<void>;\r\n}\r\n\r\nexport interface FetchRemoteEnvOptions {\r\n sshTarget: string;\r\n sshKeyPath: string;\r\n /** Absolute path to the .env file on the remote host. */\r\n remoteEnvPath: string;\r\n /** Which key to extract (default: DATABASE_PRIMARY_URL). */\r\n envKey?: string;\r\n keepaliveIntervalMs?: number;\r\n}\r\n\r\nfunction expandHome(path: string): string {\r\n if (!path.startsWith(\"~\")) return path;\r\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\r\n return join(home, path.slice(1));\r\n}\r\n\r\nfunction resolvePrivateKeyPath(input: string): string {\r\n const candidate = expandHome(input);\r\n const stripped = candidate.endsWith(\".pub\") ? candidate.slice(0, -4) : candidate;\r\n if (existsSync(stripped) && statSync(stripped).isFile()) return stripped;\r\n throw new Error(\r\n `SSH private key not found at ${stripped}. The --db-ssh-tunnel flag needs the private key (not just .pub) to open the tunnel.`,\r\n );\r\n}\r\n\r\nfunction parseSshTarget(target: string): { username: string; host: string; port: number } {\r\n const at = target.indexOf(\"@\");\r\n if (at === -1) {\r\n throw new Error(`--db-ssh-tunnel must be in the form user@host[:port], got: ${target}`);\r\n }\r\n const username = target.slice(0, at);\r\n const hostPart = target.slice(at + 1);\r\n const colon = hostPart.lastIndexOf(\":\");\r\n if (colon === -1) return { username, host: hostPart, port: 22 };\r\n const port = Number(hostPart.slice(colon + 1));\r\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\r\n throw new Error(`Invalid SSH port in --db-ssh-tunnel: ${hostPart.slice(colon + 1)}`);\r\n }\r\n return { username, host: hostPart.slice(0, colon), port };\r\n}\r\n\r\nfunction rewriteUrl(originalUrl: string, localPort: number): string {\r\n const parsed = new URL(originalUrl);\r\n parsed.hostname = \"127.0.0.1\";\r\n parsed.port = String(localPort);\r\n return parsed.toString();\r\n}\r\n\r\nasync function connectSsh(opts: {\r\n host: string;\r\n port: number;\r\n username: string;\r\n privateKey: Buffer;\r\n keepaliveIntervalMs: number;\r\n}): Promise<SshClient> {\r\n return await new Promise((resolve, reject) => {\r\n const conn = new SshClient();\r\n const onError = (err: Error) => {\r\n conn.removeAllListeners();\r\n reject(err);\r\n };\r\n conn.once(\"ready\", () => {\r\n conn.removeListener(\"error\", onError);\r\n resolve(conn);\r\n });\r\n conn.once(\"error\", onError);\r\n conn.connect({\r\n host: opts.host,\r\n port: opts.port,\r\n username: opts.username,\r\n privateKey: opts.privateKey,\r\n keepaliveInterval: opts.keepaliveIntervalMs,\r\n keepaliveCountMax: 3,\r\n readyTimeout: 20_000,\r\n });\r\n });\r\n}\r\n\r\nfunction execOverSsh(conn: SshClient, cmd: string): Promise<{ stdout: string; stderr: string; code: number }> {\r\n return new Promise((resolve, reject) => {\r\n conn.exec(cmd, (err, stream) => {\r\n if (err) {\r\n reject(err);\r\n return;\r\n }\r\n let stdout = \"\";\r\n let stderr = \"\";\r\n stream.on(\"data\", (chunk: Buffer) => {\r\n stdout += chunk.toString(\"utf8\");\r\n });\r\n stream.stderr.on(\"data\", (chunk: Buffer) => {\r\n stderr += chunk.toString(\"utf8\");\r\n });\r\n stream.on(\"close\", (code: number) => {\r\n resolve({ stdout, stderr, code: code ?? -1 });\r\n });\r\n });\r\n });\r\n}\r\n\r\nfunction parseEnvValue(content: string, key: string): string | undefined {\r\n const re = new RegExp(`^${key}\\\\s*=\\\\s*(.*)$`, \"m\");\r\n const m = content.match(re);\r\n if (!m || !m[1]) return undefined;\r\n let value = m[1].trim();\r\n if (value.length >= 2 && (value[0] === '\"' || value[0] === \"'\") && value[value.length - 1] === value[0]) {\r\n value = value.slice(1, -1);\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Connects via SSH and reads a single env var from a remote .env file.\r\n * Useful so mcp.json never has to hold the DB password — the MCP fetches it\r\n * fresh at startup from the same trusted host the tunnel terminates on.\r\n */\r\nexport async function fetchRemoteEnvValue(options: FetchRemoteEnvOptions): Promise<string> {\r\n const { username, host, port } = parseSshTarget(options.sshTarget);\r\n const privateKeyPath = resolvePrivateKeyPath(options.sshKeyPath);\r\n const privateKey = readFileSync(privateKeyPath);\r\n const keepaliveIntervalMs = options.keepaliveIntervalMs ?? 30_000;\r\n const envKey = options.envKey ?? \"DATABASE_PRIMARY_URL\";\r\n\r\n const conn = await connectSsh({ host, port, username, privateKey, keepaliveIntervalMs });\r\n try {\r\n const safePath = options.remoteEnvPath.replace(/'/g, \"'\\\\''\");\r\n const result = await execOverSsh(conn, `cat -- '${safePath}'`);\r\n if (result.code !== 0) {\r\n throw new Error(\r\n `remote cat ${options.remoteEnvPath} failed (exit ${result.code}): ${result.stderr.trim()}`,\r\n );\r\n }\r\n const value = parseEnvValue(result.stdout, envKey);\r\n if (!value) {\r\n throw new Error(`${envKey} not found in ${options.remoteEnvPath}`);\r\n }\r\n return value;\r\n } finally {\r\n conn.end();\r\n }\r\n}\r\n\r\nexport async function openDbSshTunnel(options: DbSshTunnelOptions): Promise<DbSshTunnel> {\r\n const { username, host, port } = parseSshTarget(options.sshTarget);\r\n const privateKeyPath = resolvePrivateKeyPath(options.sshKeyPath);\r\n const privateKey = readFileSync(privateKeyPath);\r\n const keepaliveIntervalMs = options.keepaliveIntervalMs ?? 30_000;\r\n\r\n const parsedDbUrl = new URL(options.databaseUrl);\r\n const remoteHost = parsedDbUrl.hostname;\r\n const remotePort = Number(parsedDbUrl.port || \"5432\");\r\n\r\n const conn = await connectSsh({ host, port, username, privateKey, keepaliveIntervalMs });\r\n conn.on(\"error\", (err) => {\r\n console.error(`[mcp][db-ssh-tunnel] ssh connection error: ${err.message}`);\r\n });\r\n conn.on(\"close\", () => {\r\n if (options.exitProcessOnSshClose !== false) {\r\n console.error(\"[mcp][db-ssh-tunnel] ssh connection closed; MCP will exit so Cursor can respawn it\");\r\n process.exit(1);\r\n }\r\n });\r\n\r\n const server: Server = createServer((local: Socket) => {\r\n conn.forwardOut(\"127.0.0.1\", 0, remoteHost, remotePort, (err: Error | undefined, stream: ClientChannel) => {\r\n if (err) {\r\n console.error(`[mcp][db-ssh-tunnel] forwardOut failed: ${err.message}`);\r\n local.destroy(err);\r\n return;\r\n }\r\n local.on(\"error\", () => stream.destroy());\r\n stream.on(\"error\", () => local.destroy());\r\n local.pipe(stream).pipe(local);\r\n });\r\n });\r\n\r\n const localPort = await new Promise<number>((resolve, reject) => {\r\n server.once(\"error\", reject);\r\n server.listen(0, \"127.0.0.1\", () => {\r\n const addr = server.address() as AddressInfo | null;\r\n if (!addr || typeof addr === \"string\") {\r\n reject(new Error(\"Failed to bind local tunnel listener\"));\r\n return;\r\n }\r\n resolve(addr.port);\r\n });\r\n });\r\n\r\n const rewrittenDatabaseUrl = rewriteUrl(options.databaseUrl, localPort);\r\n console.error(\r\n `[mcp][db-ssh-tunnel] forwarding 127.0.0.1:${localPort} -> ${remoteHost}:${remotePort} via ssh ${username}@${host}:${port}`,\r\n );\r\n\r\n return {\r\n rewrittenDatabaseUrl,\r\n localPort,\r\n async close() {\r\n await new Promise<void>((resolve) => server.close(() => resolve()));\r\n conn.end();\r\n },\r\n };\r\n}\r\n","/**\r\n * Trigger.dev MCP Tools\r\n *\r\n * SSH-based tools for managing Trigger.dev projects. All projects run on a\r\n * single Docker Compose instance. The compose project, server, postgres\r\n * container, and webapp port are auto-discovered — callers only need to\r\n * provide the Trigger.dev project slug (from trigger-list).\r\n *\r\n * @module trigger-tools\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types (mirrored from index.ts to avoid circular imports)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface SshConnectionOptions {\r\n hostname: string;\r\n port: number;\r\n username: string;\r\n password?: string;\r\n privateKey?: string;\r\n passphrase?: string;\r\n timeout?: number;\r\n}\r\n\r\ninterface SshResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n}\r\n\r\ntype SshExecFn = (\r\n conn: SshConnectionOptions,\r\n command: string,\r\n proxy?: SshConnectionOptions,\r\n) => Promise<SshResult>;\r\n\r\ntype GetServerConnectionFn = (\r\n serverId: string,\r\n) => Promise<{ conn: SshConnectionOptions; proxy?: SshConnectionOptions }>;\r\n\r\ninterface ToolResult {\r\n [key: string]: unknown;\r\n content: { type: string; text: string }[];\r\n}\r\n\r\ninterface TriggerToolDeps {\r\n sshExec: SshExecFn;\r\n getServerConnection: GetServerConnectionFn;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Trigger.dev API response shapes (partial, only fields we display)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerRunItem {\r\n id: string;\r\n status: string;\r\n taskIdentifier: string;\r\n version?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n startedAt?: string;\r\n finishedAt?: string;\r\n durationMs?: number;\r\n isTest?: boolean;\r\n}\r\n\r\ninterface TriggerRunDetail extends TriggerRunItem {\r\n payload?: unknown;\r\n output?: unknown;\r\n attempts?: {\r\n id: string;\r\n status: string;\r\n error?: { message: string; name?: string; stackTrace?: string };\r\n startedAt?: string;\r\n completedAt?: string;\r\n }[];\r\n}\r\n\r\nconst TERMINAL_STATUSES = new Set([\r\n 'COMPLETED', 'FAILED', 'CRASHED', 'CANCELED',\r\n 'SYSTEM_FAILURE', 'INTERRUPTED', 'EXPIRED',\r\n]);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hardcoded infra constants — single Trigger.dev instance\r\n// ---------------------------------------------------------------------------\r\n\r\n/** SSH server that hosts the Trigger.dev Docker Compose stack. */\r\nconst TRIGGER_SERVER_ID = '03659d55-e194-400d-b82a-bf6457371ded';\r\n\r\n/** Docker Compose project name on the server. */\r\nconst COMPOSE_PROJECT = 'mg-dashboard-supabase-trigger';\r\n\r\nconst PG_CONTAINER = `${COMPOSE_PROJECT}-postgres-1`;\r\nconst WA_CONTAINER = `${COMPOSE_PROJECT}-webapp-1`;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Tool definitions\r\n// ---------------------------------------------------------------------------\r\n\r\n/** MCP tool definitions for Trigger.dev (list projects, runs, details, test, replay). */\r\nexport const TRIGGER_TOOLS = [\r\n {\r\n name: 'trigger-list',\r\n description:\r\n 'List all Trigger.dev projects. Returns the project slug and name. ' +\r\n 'Use the slug as the \"project\" parameter in other trigger-* tools.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {},\r\n },\r\n },\r\n {\r\n name: 'trigger-runs',\r\n description:\r\n 'List recent task runs for a Trigger.dev project. ' +\r\n 'Returns run ID, task name, status, duration, and timestamps.\\n\\n' +\r\n 'Common shortcuts: `failedOnly: true` returns only FAILED/CRASHED/SYSTEM_FAILURE/INTERRUPTED/TIMED_OUT. ' +\r\n '`sinceMinutes: 60` filters to runs created in the last hour (combines with status/taskIdentifier).',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n status: {\r\n type: 'string',\r\n description: 'Comma-separated status filter: QUEUED,EXECUTING,COMPLETED,FAILED,CRASHED,CANCELED,SYSTEM_FAILURE. Ignored when failedOnly is true.',\r\n },\r\n failedOnly: {\r\n type: 'boolean',\r\n description: 'Shortcut: only return FAILED + CRASHED + SYSTEM_FAILURE + INTERRUPTED + TIMED_OUT runs. Overrides `status` when true.',\r\n },\r\n taskIdentifier: { type: 'string', description: 'Filter by task identifier (e.g. \"hello-world\")' },\r\n sinceMinutes: { type: 'number', description: 'Only runs created in the last N minutes (uses Trigger filter[from]). Max 10080 (= 1 week).' },\r\n limit: { type: 'number', description: 'Max runs to return (default 20, max 100)' },\r\n },\r\n required: ['project'],\r\n },\r\n },\r\n {\r\n name: 'trigger-run',\r\n description:\r\n 'Inspect, create, or replay a Trigger.dev run. Pick the mode with `action`:\\n' +\r\n '- \"detail\": fetch full run state — status, payload, output, error stack traces, and logs. Required: runId.\\n' +\r\n '- \"test\": kick off a task run and (by default) wait for it to complete, returning the final detail in one shot. Required: taskId. Optional: payload (JSON string), waitSeconds (default 60, max 300, set 0 to fire-and-forget).\\n' +\r\n '- \"replay\": re-run a previously failed/completed run with the same payload. Required: runId. Optional: waitSeconds (when >0, also waits for the new run to finish and returns its full detail).\\n\\n' +\r\n 'Tip: replace any old `trigger-run-detail` / `trigger-test-task` / `trigger-replay-run` calls with this single tool — output format is identical.',\r\n inputSchema: {\r\n type: 'object' as const,\r\n properties: {\r\n action: { type: 'string', enum: ['detail', 'test', 'replay'], description: 'Which run operation to perform.' },\r\n project: { type: 'string', description: 'Project slug from trigger-list (e.g. \"mg-dashboard-bHfS\")' },\r\n runId: { type: 'string', description: 'Run ID (e.g. run_xxxxx). Required for action=\"detail\" or action=\"replay\".' },\r\n taskId: { type: 'string', description: 'Task identifier (e.g. \"hello-world\"). Required for action=\"test\".' },\r\n payload: { type: 'string', description: 'JSON payload string passed to the task (action=\"test\" only).' },\r\n waitSeconds: { type: 'number', description: 'Max seconds to wait for completion. Default 60 (action=\"test\") / 0 (action=\"replay\", fire-and-forget). Max 300. Set 0 to skip the wait.' },\r\n },\r\n required: ['action', 'project'],\r\n },\r\n },\r\n];\r\n\r\n/** Set of Trigger.dev MCP tool names for fast membership checks in the main server switch. */\r\nexport const TRIGGER_TOOL_NAMES = new Set(TRIGGER_TOOLS.map((t) => t.name));\r\n\r\n/** Maps each Trigger.dev tool name to the dashboard module key required to use it (`ci_cd`). */\r\nexport const TRIGGER_TOOL_MODULE_MAP: Record<string, string> = {\r\n 'trigger-list': 'ci_cd',\r\n 'trigger-runs': 'ci_cd',\r\n 'trigger-run': 'ci_cd',\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// SSH helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TriggerInstance {\r\n port: string;\r\n apiKey: string;\r\n}\r\n\r\n/**\r\n * Discover the webapp port and the production API key for a specific\r\n * Trigger.dev project by querying Docker and the Postgres container.\r\n * The API key is resolved via a JOIN on Project → RuntimeEnvironment.\r\n */\r\nasync function discoverInstance(\r\n projectSlug: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<TriggerInstance> {\r\n const sql = `SELECT re.\\\\\"apiKey\\\\\" FROM \\\\\"RuntimeEnvironment\\\\\" re `\r\n + `JOIN \\\\\"Project\\\\\" p ON re.\\\\\"projectId\\\\\" = p.id `\r\n + `WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;\r\n\r\n const cmd = [\r\n `PORT=$(docker port \"${WA_CONTAINER}\" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,\r\n `KEY=$(docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null | tr -d '[:space:]')`,\r\n 'echo \"$PORT|$KEY\"',\r\n ].join(' && ');\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n const sepIdx = output.indexOf('|');\r\n\r\n const port = sepIdx > 0 ? output.substring(0, sepIdx) : '';\r\n const apiKey = sepIdx > 0 ? output.substring(sepIdx + 1) : '';\r\n\r\n if (!port) {\r\n throw new Error(\r\n `Could not find webapp port for ${WA_CONTAINER}. Is the container running?`,\r\n );\r\n }\r\n if (!apiKey) {\r\n throw new Error(\r\n `Could not get API key for project \"${projectSlug}\". ` +\r\n 'Check if the project slug is correct (use trigger-list).',\r\n );\r\n }\r\n\r\n return { port, apiKey };\r\n}\r\n\r\n/**\r\n * Fetch console/logger output for a run from the TaskEvent table in Postgres.\r\n * Returns formatted log lines sorted by time, filtered to user-relevant levels.\r\n */\r\nasync function fetchRunLogs(\r\n runId: string,\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n): Promise<string> {\r\n const sql = `SELECT level, message, \\\\\"isError\\\\\", \\\\\"createdAt\\\\\" `\r\n + `FROM \\\\\"TaskEvent\\\\\" `\r\n + `WHERE \\\\\"runId\\\\\" = '${runId}' `\r\n + `AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') `\r\n + `ORDER BY \\\\\"startTime\\\\\" ASC LIMIT 200`;\r\n\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) return '';\r\n\r\n return output.split('\\n').map((line) => {\r\n const parts = line.split('|');\r\n const level = (parts[0] || '').padEnd(5);\r\n const message = parts[1] || '';\r\n const isError = parts[2] === 't';\r\n const ts = parts[3] || '';\r\n const time = ts ? ts.split(' ')[1]?.substring(0, 8) || '' : '';\r\n const prefix = isError ? '!' : ' ';\r\n return `${prefix}${time} [${level}] ${message}`;\r\n }).join('\\n');\r\n}\r\n\r\n/**\r\n * Execute a curl request against the Trigger.dev REST API via SSH.\r\n * Uses -g (globoff) to prevent curl from interpreting brackets in URLs.\r\n */\r\nasync function triggerApi(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n method: string,\r\n path: string,\r\n body?: string,\r\n): Promise<string> {\r\n const parts = ['curl', '-s', '-g', '--max-time', '30'];\r\n if (method !== 'GET') parts.push('-X', method);\r\n parts.push(`\"http://localhost:${instance.port}${path}\"`);\r\n parts.push(`-H \"Authorization: Bearer ${instance.apiKey}\"`);\r\n if (body) {\r\n parts.push('-H \"Content-Type: application/json\"');\r\n parts.push(`-d '${body.replace(/'/g, \"'\\\\''\")}'`);\r\n }\r\n\r\n const result = await sshExec(conn, parts.join(' '), proxy);\r\n if (result.exitCode !== 0 && !result.stdout) {\r\n throw new Error(\r\n `Trigger.dev API call failed (${method} ${path}): ${result.stderr || `exit code ${result.exitCode}`}`,\r\n );\r\n }\r\n return result.stdout;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatters\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction formatRunsTable(runs: TriggerRunItem[]): string {\r\n if (runs.length === 0) return 'No runs found';\r\n\r\n const lines = runs.map((r) => {\r\n const duration = r.durationMs != null ? `${(r.durationMs / 1000).toFixed(1)}s` : '-';\r\n const test = r.isTest ? ' [TEST]' : '';\r\n const created = r.createdAt ? new Date(r.createdAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' }) : '';\r\n return `${r.id} ${r.taskIdentifier.padEnd(35)} ${r.status.padEnd(16)} ${duration.padStart(8)} ${created}${test}`;\r\n });\r\n\r\n return `${'ID'.padEnd(20)} ${'TASK'.padEnd(35)} ${'STATUS'.padEnd(16)} ${'DURATION'.padStart(8)} CREATED\\n` +\r\n '-'.repeat(110) + '\\n' +\r\n lines.join('\\n');\r\n}\r\n\r\nfunction formatRunDetail(run: TriggerRunDetail): string {\r\n const sections: string[] = [];\r\n\r\n sections.push(`=== Run ${run.id} ===`);\r\n sections.push(`Task: ${run.taskIdentifier}`);\r\n sections.push(`Status: ${run.status}`);\r\n sections.push(`Version: ${run.version || '-'}`);\r\n\r\n if (run.startedAt) sections.push(`Started: ${new Date(run.startedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.finishedAt) sections.push(`Finished: ${new Date(run.finishedAt).toLocaleString('nl-NL', { timeZone: 'Europe/Amsterdam' })}`);\r\n if (run.durationMs != null) sections.push(`Duration: ${(run.durationMs / 1000).toFixed(2)}s`);\r\n\r\n if (run.payload !== undefined) {\r\n const payloadStr = typeof run.payload === 'string'\r\n ? run.payload\r\n : JSON.stringify(run.payload, null, 2);\r\n sections.push('', '--- Payload ---', payloadStr);\r\n }\r\n\r\n if (run.output !== undefined) {\r\n const outputStr = typeof run.output === 'string'\r\n ? run.output\r\n : JSON.stringify(run.output, null, 2);\r\n sections.push('', '--- Output ---', outputStr);\r\n }\r\n\r\n if (run.attempts && run.attempts.length > 0) {\r\n for (const attempt of run.attempts) {\r\n if (attempt.error) {\r\n sections.push(\r\n '',\r\n `--- Error (${attempt.id}) ---`,\r\n `${attempt.error.name || 'Error'}: ${attempt.error.message}`,\r\n );\r\n if (attempt.error.stackTrace) {\r\n sections.push('', attempt.error.stackTrace);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main handler\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Executes a Trigger.dev–related MCP tool over SSH against the shared Docker Compose stack.\r\n *\r\n * @param name - Tool name (e.g. `trigger-list`, `trigger-runs`).\r\n * @param args - Arguments from the MCP `callTool` request.\r\n * @param deps - Injected `sshExec` and `getServerConnection` implementations.\r\n * @returns MCP-formatted result with human-readable text content.\r\n * @throws {Error} When a JSON payload for `trigger-test-task` is invalid, or discovery/API calls fail critically.\r\n */\r\nexport async function handleTriggerTool(\r\n name: string,\r\n args: Record<string, unknown>,\r\n deps: TriggerToolDeps,\r\n): Promise<ToolResult> {\r\n const { sshExec, getServerConnection } = deps;\r\n const { conn, proxy } = await getServerConnection(TRIGGER_SERVER_ID);\r\n\r\n switch (name) {\r\n // -----------------------------------------------------------------\r\n case 'trigger-list': {\r\n const sql = 'SELECT slug, name FROM \\\\\"Project\\\\\" ORDER BY name';\r\n const cmd = `docker exec \"${PG_CONTAINER}\" psql -U postgres -d main -t -A -c \"${sql}\" 2>/dev/null`;\r\n\r\n const result = await sshExec(conn, cmd, proxy);\r\n const output = result.stdout.trim();\r\n\r\n if (!output) {\r\n return { content: [{ type: 'text', text: 'No Trigger.dev projects found.' }] };\r\n }\r\n\r\n const header = `${'SLUG'.padEnd(25)} NAME`;\r\n const sep = '-'.repeat(55);\r\n const lines = output.split('\\n').map((line) => {\r\n const [slug, name] = line.split('|');\r\n return `${(slug || '').padEnd(25)} ${name || ''}`;\r\n });\r\n\r\n return { content: [{ type: 'text', text: `${header}\\n${sep}\\n${lines.join('\\n')}` }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-runs': {\r\n const project = String(args.project);\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 100);\r\n const queryParts = [`page%5Bsize%5D=${limit}`];\r\n\r\n const failedOnly = args.failedOnly === true;\r\n const statusArg = failedOnly\r\n ? 'FAILED,CRASHED,SYSTEM_FAILURE,INTERRUPTED,TIMED_OUT'\r\n : (args.status ? String(args.status) : '');\r\n if (statusArg) queryParts.push(`filter%5Bstatus%5D=${encodeURIComponent(statusArg)}`);\r\n\r\n if (args.taskIdentifier) {\r\n queryParts.push(`filter%5BtaskIdentifier%5D=${encodeURIComponent(String(args.taskIdentifier))}`);\r\n }\r\n\r\n const sinceMinutes = Number(args.sinceMinutes);\r\n if (Number.isFinite(sinceMinutes) && sinceMinutes > 0) {\r\n const capped = Math.min(sinceMinutes, 10080);\r\n const fromMs = Date.now() - capped * 60_000;\r\n queryParts.push(`filter%5Bfrom%5D=${fromMs}`);\r\n }\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v1/runs?${queryParts.join('&')}`,\r\n );\r\n\r\n let parsed: { data?: TriggerRunItem[] };\r\n try {\r\n parsed = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runs = parsed.data || [];\r\n return { content: [{ type: 'text', text: formatRunsTable(runs) }] };\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n case 'trigger-run': {\r\n const action = String(args.action);\r\n if (action !== 'detail' && action !== 'test' && action !== 'replay') {\r\n return { content: [{ type: 'text', text: 'Error: action must be one of: detail, test, replay' }] };\r\n }\r\n const project = String(args.project);\r\n\r\n if (action === 'detail') {\r\n const runId = String(args.runId ?? '');\r\n if (!runId) return { content: [{ type: 'text', text: 'Error: action=\"detail\" requires runId' }] };\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n return await fetchAndFormatRun(conn, proxy, sshExec, instance, runId);\r\n }\r\n\r\n if (action === 'test') {\r\n const taskId = String(args.taskId ?? '');\r\n if (!taskId) return { content: [{ type: 'text', text: 'Error: action=\"test\" requires taskId' }] };\r\n\r\n const waitArg = args.waitSeconds === undefined ? 60 : Number(args.waitSeconds);\r\n const waitSeconds = Math.min(Math.max(Number.isFinite(waitArg) ? waitArg : 60, 0), 300);\r\n conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n let payload = '{}';\r\n if (args.payload) {\r\n try {\r\n JSON.parse(String(args.payload));\r\n payload = String(args.payload);\r\n } catch {\r\n throw new Error(`Invalid JSON payload: ${String(args.payload).substring(0, 200)}`);\r\n }\r\n }\r\n\r\n const triggerBody = JSON.stringify({\r\n payload: JSON.parse(payload),\r\n options: { tags: ['mcp-test'], test: true },\r\n });\r\n\r\n const triggerJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/tasks/${encodeURIComponent(taskId)}/trigger`,\r\n triggerBody,\r\n );\r\n\r\n let triggerResp: { id?: string };\r\n try {\r\n triggerResp = JSON.parse(triggerJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Failed to trigger task. API response:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n const runId = triggerResp.id;\r\n if (!runId) {\r\n return { content: [{ type: 'text', text: `Trigger API did not return a run ID:\\n${triggerJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (waitSeconds === 0) {\r\n return { content: [{ type: 'text', text: `Run triggered. ID: ${runId} (fire-and-forget; use action=\"detail\" to check).` }] };\r\n }\r\n\r\n return await waitForCompletion(conn, proxy, sshExec, instance, runId, waitSeconds);\r\n }\r\n\r\n // action === 'replay'\r\n const runId = String(args.runId ?? '');\r\n if (!runId) return { content: [{ type: 'text', text: 'Error: action=\"replay\" requires runId' }] };\r\n\r\n const waitArg = args.waitSeconds === undefined ? 0 : Number(args.waitSeconds);\r\n const waitSeconds = Math.min(Math.max(Number.isFinite(waitArg) ? waitArg : 0, 0), 300);\r\n if (waitSeconds > 0) conn.timeout = (waitSeconds + 30) * 1000;\r\n\r\n const instance = await discoverInstance(project, conn, proxy, sshExec);\r\n\r\n const rawJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'POST', `/api/v1/runs/${encodeURIComponent(runId)}/replay`,\r\n );\r\n\r\n let result: { id?: string };\r\n try {\r\n result = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (!result.id) {\r\n return { content: [{ type: 'text', text: `Replay response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n if (waitSeconds === 0) {\r\n return { content: [{ type: 'text', text: `Run replayed. New run ID: ${result.id} (use action=\"detail\" to check status).` }] };\r\n }\r\n\r\n return await waitForCompletion(conn, proxy, sshExec, instance, result.id, waitSeconds);\r\n }\r\n\r\n // -----------------------------------------------------------------\r\n default:\r\n return { content: [{ type: 'text', text: `Unknown trigger tool: ${name}` }] };\r\n }\r\n}\r\n\r\n/** Fetch a run by ID and format it together with its console/logger output. */\r\nasync function fetchAndFormatRun(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n runId: string,\r\n): Promise<ToolResult> {\r\n const [rawJson, logs] = await Promise.all([\r\n triggerApi(conn, proxy, sshExec, instance, 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`),\r\n fetchRunLogs(runId, conn, proxy, sshExec),\r\n ]);\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(rawJson);\r\n } catch {\r\n return { content: [{ type: 'text', text: `Invalid API response:\\n${rawJson.substring(0, 500)}` }] };\r\n }\r\n\r\n let text = formatRunDetail(run);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n}\r\n\r\n/** Poll a run until terminal status or budget expires, then return full detail. */\r\nasync function waitForCompletion(\r\n conn: SshConnectionOptions,\r\n proxy: SshConnectionOptions | undefined,\r\n sshExec: SshExecFn,\r\n instance: TriggerInstance,\r\n runId: string,\r\n waitSeconds: number,\r\n): Promise<ToolResult> {\r\n const pollInterval = 3000;\r\n const maxPolls = Math.ceil((waitSeconds * 1000) / pollInterval);\r\n\r\n for (let i = 0; i < maxPolls; i++) {\r\n await new Promise((r) => setTimeout(r, pollInterval));\r\n\r\n const pollJson = await triggerApi(\r\n conn, proxy, sshExec, instance,\r\n 'GET', `/api/v3/runs/${encodeURIComponent(runId)}`,\r\n );\r\n\r\n let run: TriggerRunDetail;\r\n try {\r\n run = JSON.parse(pollJson);\r\n } catch {\r\n continue;\r\n }\r\n\r\n if (TERMINAL_STATUSES.has(run.status)) {\r\n let text = formatRunDetail(run);\r\n const logs = await fetchRunLogs(runId, conn, proxy, sshExec);\r\n if (logs) text += '\\n\\n--- Logs ---\\n' + logs;\r\n return { content: [{ type: 'text', text }] };\r\n }\r\n }\r\n\r\n return {\r\n content: [{\r\n type: 'text',\r\n text: `Run ${runId} did not complete within ${waitSeconds}s (still running). Use action=\"detail\" with this runId to check later.`,\r\n }],\r\n };\r\n}\r\n","throw new Error(\n \"This module cannot be imported from a Client Component module. \" +\n \"It should only be used from a Server Component.\"\n);\n"]}
|