@onyxsecurity/mcp-gateway 2.1.2 → 2.1.3

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.
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{hideBin as e,recordKeychainOutcome as t,setupProxyDispatcher as n,yargs_default as r}from"../helpers-BrpBfS5F.js";await n();const i=r(e(process.argv)).parserConfiguration({"populate--":!0,"unknown-options-as-args":!0}).option(`access-control-url`,{type:`string`}).option(`oauth-providers-url`,{type:`string`}).option(`scanner-api-key`,{type:`string`}).option(`scanner-fail-open`,{type:`boolean`}).option(`scanner-timeout-ms`,{type:`number`}).option(`scanner-url`,{type:`string`}).help(!1).version(!1).parseSync();if(String(i._[0]??``)===`probe`){i.oauthProvidersUrl&&(process.env.MCP_GATEWAY_OAUTH_PROVIDERS_URL=i.oauthProvidersUrl),i.scannerApiKey&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=i.scannerApiKey);let{config:e}=await import(`../env-GMZEjgdX.js`),{initializeOAuthProviders:t}=await import(`../oauthProvidersClient-C2189wCN.js`),{runProbeCli:n}=await import(`../cli-B7Q_QKa8.js`);await t(e.oauthProviders),process.exitCode=await n()}else{i.accessControlUrl&&(process.env.MCP_GATEWAY_ACCESS_CONTROL_URL=i.accessControlUrl),i.oauthProvidersUrl&&(process.env.MCP_GATEWAY_OAUTH_PROVIDERS_URL=i.oauthProvidersUrl),i.scannerApiKey&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=i.scannerApiKey),i.scannerFailOpen!==void 0&&(process.env.MCP_GATEWAY_SCANNER_FAIL_OPEN=String(i.scannerFailOpen)),i.scannerTimeoutMs!==void 0&&(process.env.MCP_GATEWAY_SCANNER_TIMEOUT_MS=String(i.scannerTimeoutMs)),i.scannerUrl&&(process.env.MCP_GATEWAY_SCANNER_URL=i.scannerUrl);let e=`missing`;if(process.env.MCP_GATEWAY_SCANNER_API_KEY)e=`env`;else if(process.env.MCP_GATEWAY_DISABLE_KEYCHAIN===`1`)e=`missing`;else try{let{ACCOUNT_DEFAULT:t,resolveApiKeyFromStore:n}=await import(`../secretstore-B7UBzLo4.js`),{key:r,source:i}=await n(t);r&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=r,process.env.MCP_GATEWAY_MIRROR_API_KEY||(process.env.MCP_GATEWAY_MIRROR_API_KEY=r)),e=i}catch{e=`error`}t(e),process.stderr.write(JSON.stringify({caller:`gateway_startup`,event:`keychain_outcome`,keychain_disabled_env_set:process.env.MCP_GATEWAY_DISABLE_KEYCHAIN===`1`,op:`get`,outcome:e,platform:process.platform,reason:e})+`
3
- `);let{main:n}=await import(`../main-pbLwxioE.js`);await n()}export{};
2
+ import{hideBin as e,recordKeychainOutcome as t,setupProxyDispatcher as n,yargs_default as r}from"../helpers-BrpBfS5F.js";await n();const i=r(e(process.argv)).parserConfiguration({"populate--":!0,"unknown-options-as-args":!0}).option(`access-control-url`,{type:`string`}).option(`oauth-providers-url`,{type:`string`}).option(`scanner-api-key`,{type:`string`}).option(`scanner-fail-open`,{type:`boolean`}).option(`scanner-timeout-ms`,{type:`number`}).option(`scanner-url`,{type:`string`}).help(!1).version(!1).parseSync();if(String(i._[0]??``)===`probe`){i.oauthProvidersUrl&&(process.env.MCP_GATEWAY_OAUTH_PROVIDERS_URL=i.oauthProvidersUrl),i.scannerApiKey&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=i.scannerApiKey);let{config:e}=await import(`../env-Bs820sh8.js`),{initializeOAuthProviders:t}=await import(`../oauthProvidersClient-CI3cndJj.js`),{runProbeCli:n}=await import(`../cli-C3ziJuw5.js`);await t(e.oauthProviders),process.exitCode=await n()}else{i.accessControlUrl&&(process.env.MCP_GATEWAY_ACCESS_CONTROL_URL=i.accessControlUrl),i.oauthProvidersUrl&&(process.env.MCP_GATEWAY_OAUTH_PROVIDERS_URL=i.oauthProvidersUrl),i.scannerApiKey&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=i.scannerApiKey),i.scannerFailOpen!==void 0&&(process.env.MCP_GATEWAY_SCANNER_FAIL_OPEN=String(i.scannerFailOpen)),i.scannerTimeoutMs!==void 0&&(process.env.MCP_GATEWAY_SCANNER_TIMEOUT_MS=String(i.scannerTimeoutMs)),i.scannerUrl&&(process.env.MCP_GATEWAY_SCANNER_URL=i.scannerUrl);let e=`missing`;if(process.env.MCP_GATEWAY_SCANNER_API_KEY)e=`env`;else if(process.env.MCP_GATEWAY_DISABLE_KEYCHAIN===`1`)e=`missing`;else try{let{ACCOUNT_DEFAULT:t,resolveApiKeyFromStore:n}=await import(`../secretstore-B7UBzLo4.js`),{key:r,source:i}=await n(t);r&&(process.env.MCP_GATEWAY_SCANNER_API_KEY=r,process.env.MCP_GATEWAY_MIRROR_API_KEY||(process.env.MCP_GATEWAY_MIRROR_API_KEY=r)),e=i}catch{e=`error`}t(e),process.stderr.write(JSON.stringify({caller:`gateway_startup`,event:`keychain_outcome`,keychain_disabled_env_set:process.env.MCP_GATEWAY_DISABLE_KEYCHAIN===`1`,op:`get`,outcome:e,platform:process.platform,reason:e})+`
3
+ `);let{main:n}=await import(`../main-Mkq23qZ6.js`);await n()}export{};
4
4
  //# sourceMappingURL=mcp-gateway.js.map
@@ -1,3 +1,3 @@
1
- import"./normalizeUrl-BrUSzVK4.js";import"./env-Be4mEx1x.js";import"./logger-DSLFCg6q.js";import{findProviderForUrl as e}from"./providers-AU_rp6kE.js";import{AuthServerDiscoveryError as t,discoverAuthServer as n,getDcrClientName as r,getDcrClientUri as i,getDcrRedirectUris as a,walkTransports as o}from"./transportDetection-CDs4ZX0V.js";async function s(e,t={}){let n=t.perServerTimeoutMs??15e3,r=t.maxRetries??1,i=t.retryDelayMs??200;return{results:await Promise.all(e.servers.map(e=>y(e.url,n,r,i)))}}async function c(e,t,n){let r=await fetch(e,{body:JSON.stringify(t),headers:{Accept:`application/json`,"Content-Type":`application/json`},method:`POST`,signal:n});if(r.status===200||r.status===201)try{let e=await r.json();return typeof e.client_id!=`string`||e.client_id.length===0?{status:r.status}:{body:e,status:r.status}}catch{return{status:r.status}}let i;try{i=(await r.text()).trim()}catch{}let a;return(r.status===429||r.status>=500)&&(a=g(r.headers.get(`Retry-After`))),{errorBody:i,retryAfterMs:a,status:r.status}}async function l(e,t){let{result:n}=await o(async n=>{let r=n===`streamable-http`?await _(e,t):await p(e,t);if(r.body?.cancel().catch(()=>{}),r.status===404||r.status===405)throw Object.assign(Error(`${n} returned ${r.status}`),{status:r.status});return r});return n}function u(e){return e<=0?0:Math.min(e,5e3)}function d(e){return e instanceof Error?e.message:String(e)}function f(e){if(e){try{let t=JSON.parse(e);if(t.error_description)return t.error_description;if(t.error)return t.error}catch{}return e.length>200?`${e.slice(0,200)}...`:e}}async function p(e,t){return fetch(e,{headers:{Accept:`text/event-stream`},method:`GET`,signal:t})}function m(e){return!!(e.reason===`network_error`&&!e.authServer||e.reason===`dcr_rejected`&&h(e.httpStatus))}function h(e){return e?e===429?!0:e>=500&&e<600:!1}function g(e){if(!e)return;let t=e.trim();if(!t)return;let n=Number(t);if(Number.isFinite(n))return u(n*1e3);let r=Date.parse(t);if(Number.isFinite(r)){let e=r-Date.now();return e>0?u(e):0}}async function _(e,t){return fetch(e,{body:JSON.stringify({id:1,jsonrpc:`2.0`,method:`initialize`,params:{capabilities:{},clientInfo:{name:`mcp-gateway-probe`,version:`1.0`},protocolVersion:`2024-11-05`}}),headers:{Accept:`application/json, text/event-stream`,"Content-Type":`application/json`},method:`POST`,signal:t})}async function v(o,s){let u=new URL(o);if(e(u))return{authType:`oauth_pre_registered`,reason:`pre_registered_provider`,url:o};let p;try{p=await l(o,s)}catch(e){return{authType:`probe_failed`,errorDetail:d(e),reason:`network_error`,url:o}}if(p.ok)return{authType:`public`,reason:`no_auth_required`,url:o};if(p.status!==401)return{authType:`probe_failed`,errorDetail:`initialize returned status ${p.status}`,httpStatus:p.status,reason:`network_error`,url:o};let m,h;try{let e=await n(u,{signal:s});m=e.authMetadata,h=e.authServerUrl}catch(e){return{authServer:e instanceof t?e.authServerUrl.toString():void 0,authType:`probe_failed`,errorDetail:d(e),reason:`auth_metadata_discovery_failed`,url:o}}if(!m)return{authServer:h.toString(),authType:`oauth_dcr_not_supported`,reason:`no_auth_metadata`,url:o};if(!m.registration_endpoint)return{authServer:h.toString(),authType:`oauth_dcr_not_supported`,reason:`no_registration_endpoint`,url:o};let g=i(),_={client_name:r(),...g&&{client_uri:g},grant_types:[`authorization_code`,`refresh_token`],redirect_uris:a(u,`http://localhost:0/callback`),response_types:[`code`],token_endpoint_auth_method:`none`},v;try{v=await c(m.registration_endpoint,_,s)}catch(e){return{authServer:h.toString(),authType:`probe_failed`,errorDetail:d(e),reason:`network_error`,url:o}}return v.status!==200&&v.status!==201?{authServer:h.toString(),authType:`oauth_dcr_not_supported`,errorDetail:f(v.errorBody),httpStatus:v.status,reason:`dcr_rejected`,retryAfterMs:v.retryAfterMs,url:o}:v.body?{authServer:h.toString(),authType:`oauth_dcr`,reason:`dcr_success`,url:o}:{authServer:h.toString(),authType:`oauth_dcr_not_supported`,errorDetail:`DCR returned ${v.status} with unparseable body`,httpStatus:v.status,reason:`dcr_rejected`,url:o}}async function y(e,t,n,r){let i=await b(e,t);for(let a=0;a<n;a++){if(!m(i))return i;let n=Math.max(r,i.retryAfterMs??0);n>0&&await new Promise(e=>setTimeout(e,n)),i=await b(e,t)}return i}async function b(e,t){let n=new AbortController,r,i=new Promise(i=>{r=setTimeout(()=>{n.abort(),i({authType:`probe_failed`,errorDetail:`probe timed out after ${t}ms`,reason:`probe_timeout`,url:e})},t)}),a=v(e,n.signal).catch(r=>({authType:`probe_failed`,errorDetail:n.signal.aborted?`probe timed out after ${t}ms`:d(r),reason:n.signal.aborted?`probe_timeout`:`network_error`,url:e}));try{return await Promise.race([a,i])}finally{r&&clearTimeout(r)}}async function x(){let e;try{e=await C()}catch(e){let t=e instanceof Error?e.message:String(e);return process.stderr.write(`probe: failed to read stdin: ${t}\n`),2}let t;try{t=JSON.parse(e)}catch(e){let t=e instanceof Error?e.message:String(e);return process.stderr.write(`probe: stdin was not valid JSON: ${t}\n`),2}if(!S(t))return process.stderr.write(`probe: invalid input — expected {"servers":[{"url":"..."}]}
1
+ import"./normalizeUrl-BrUSzVK4.js";import"./env-DRmaf9c0.js";import"./logger-ztMIFOl1.js";import{findProviderForUrl as e}from"./providers-DAy7GGV1.js";import{AuthServerDiscoveryError as t,discoverAuthServer as n,getDcrClientName as r,getDcrClientUri as i,getDcrRedirectUris as a,walkTransports as o}from"./transportDetection-V3wf9Ve_.js";async function s(e,t={}){let n=t.perServerTimeoutMs??15e3,r=t.maxRetries??1,i=t.retryDelayMs??200;return{results:await Promise.all(e.servers.map(e=>y(e.url,n,r,i)))}}async function c(e,t,n){let r=await fetch(e,{body:JSON.stringify(t),headers:{Accept:`application/json`,"Content-Type":`application/json`},method:`POST`,signal:n});if(r.status===200||r.status===201)try{let e=await r.json();return typeof e.client_id!=`string`||e.client_id.length===0?{status:r.status}:{body:e,status:r.status}}catch{return{status:r.status}}let i;try{i=(await r.text()).trim()}catch{}let a;return(r.status===429||r.status>=500)&&(a=g(r.headers.get(`Retry-After`))),{errorBody:i,retryAfterMs:a,status:r.status}}async function l(e,t){let{result:n}=await o(async n=>{let r=n===`streamable-http`?await _(e,t):await p(e,t);if(r.body?.cancel().catch(()=>{}),r.status===404||r.status===405)throw Object.assign(Error(`${n} returned ${r.status}`),{status:r.status});return r});return n}function u(e){return e<=0?0:Math.min(e,5e3)}function d(e){return e instanceof Error?e.message:String(e)}function f(e){if(e){try{let t=JSON.parse(e);if(t.error_description)return t.error_description;if(t.error)return t.error}catch{}return e.length>200?`${e.slice(0,200)}...`:e}}async function p(e,t){return fetch(e,{headers:{Accept:`text/event-stream`},method:`GET`,signal:t})}function m(e){return!!(e.reason===`network_error`&&!e.authServer||e.reason===`dcr_rejected`&&h(e.httpStatus))}function h(e){return e?e===429?!0:e>=500&&e<600:!1}function g(e){if(!e)return;let t=e.trim();if(!t)return;let n=Number(t);if(Number.isFinite(n))return u(n*1e3);let r=Date.parse(t);if(Number.isFinite(r)){let e=r-Date.now();return e>0?u(e):0}}async function _(e,t){return fetch(e,{body:JSON.stringify({id:1,jsonrpc:`2.0`,method:`initialize`,params:{capabilities:{},clientInfo:{name:`mcp-gateway-probe`,version:`1.0`},protocolVersion:`2024-11-05`}}),headers:{Accept:`application/json, text/event-stream`,"Content-Type":`application/json`},method:`POST`,signal:t})}async function v(o,s){let u=new URL(o);if(e(u))return{authType:`oauth_pre_registered`,reason:`pre_registered_provider`,url:o};let p;try{p=await l(o,s)}catch(e){return{authType:`probe_failed`,errorDetail:d(e),reason:`network_error`,url:o}}if(p.ok)return{authType:`public`,reason:`no_auth_required`,url:o};if(p.status!==401)return{authType:`probe_failed`,errorDetail:`initialize returned status ${p.status}`,httpStatus:p.status,reason:`network_error`,url:o};let m,h;try{let e=await n(u,{signal:s});m=e.authMetadata,h=e.authServerUrl}catch(e){return{authServer:e instanceof t?e.authServerUrl.toString():void 0,authType:`probe_failed`,errorDetail:d(e),reason:`auth_metadata_discovery_failed`,url:o}}if(!m)return{authServer:h.toString(),authType:`oauth_dcr_not_supported`,reason:`no_auth_metadata`,url:o};if(!m.registration_endpoint)return{authServer:h.toString(),authType:`oauth_dcr_not_supported`,reason:`no_registration_endpoint`,url:o};let g=i(),_={client_name:r(),...g&&{client_uri:g},grant_types:[`authorization_code`,`refresh_token`],redirect_uris:a(u,`http://localhost:0/callback`),response_types:[`code`],token_endpoint_auth_method:`none`},v;try{v=await c(m.registration_endpoint,_,s)}catch(e){return{authServer:h.toString(),authType:`probe_failed`,errorDetail:d(e),reason:`network_error`,url:o}}return v.status!==200&&v.status!==201?{authServer:h.toString(),authType:`oauth_dcr_not_supported`,errorDetail:f(v.errorBody),httpStatus:v.status,reason:`dcr_rejected`,retryAfterMs:v.retryAfterMs,url:o}:v.body?{authServer:h.toString(),authType:`oauth_dcr`,reason:`dcr_success`,url:o}:{authServer:h.toString(),authType:`oauth_dcr_not_supported`,errorDetail:`DCR returned ${v.status} with unparseable body`,httpStatus:v.status,reason:`dcr_rejected`,url:o}}async function y(e,t,n,r){let i=await b(e,t);for(let a=0;a<n;a++){if(!m(i))return i;let n=Math.max(r,i.retryAfterMs??0);n>0&&await new Promise(e=>setTimeout(e,n)),i=await b(e,t)}return i}async function b(e,t){let n=new AbortController,r,i=new Promise(i=>{r=setTimeout(()=>{n.abort(),i({authType:`probe_failed`,errorDetail:`probe timed out after ${t}ms`,reason:`probe_timeout`,url:e})},t)}),a=v(e,n.signal).catch(r=>({authType:`probe_failed`,errorDetail:n.signal.aborted?`probe timed out after ${t}ms`:d(r),reason:n.signal.aborted?`probe_timeout`:`network_error`,url:e}));try{return await Promise.race([a,i])}finally{r&&clearTimeout(r)}}async function x(){let e;try{e=await C()}catch(e){let t=e instanceof Error?e.message:String(e);return process.stderr.write(`probe: failed to read stdin: ${t}\n`),2}let t;try{t=JSON.parse(e)}catch(e){let t=e instanceof Error?e.message:String(e);return process.stderr.write(`probe: stdin was not valid JSON: ${t}\n`),2}if(!S(t))return process.stderr.write(`probe: invalid input — expected {"servers":[{"url":"..."}]}
2
2
  `),2;let n=await s(t);return process.stdout.write(`${JSON.stringify(n)}\n`),0}function S(e){if(!e||typeof e!=`object`)return!1;let t=e.servers;return Array.isArray(t)?t.every(e=>e&&typeof e==`object`&&typeof e.url==`string`):!1}async function C(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}export{x as runProbeCli};
3
- //# sourceMappingURL=cli-B7Q_QKa8.js.map
3
+ //# sourceMappingURL=cli-C3ziJuw5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-B7Q_QKa8.js","names":["errorBody: string | undefined","retryAfterMs: number | undefined","initResponse: Response","authMetadata: Awaited<ReturnType<typeof discoverAuthServer>>[\"authMetadata\"]","authServerUrl: URL","clientMetadata: OAuthClientMetadata","dcr: Awaited<ReturnType<typeof attemptDcr>>","timerId: ReturnType<typeof setTimeout> | undefined","raw: string","parsed: unknown","chunks: Buffer[]"],"sources":["../src/probe/index.ts","../src/probe/cli.ts"],"sourcesContent":["import type { OAuthClientMetadata } from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nimport { AuthServerDiscoveryError, discoverAuthServer } from \"../auth/discovery.js\";\nimport { getDcrClientName, getDcrClientUri, getDcrRedirectUris } from \"../auth/oauthFlow.js\";\nimport { findProviderForUrl } from \"../auth/providers.js\";\nimport { walkTransports } from \"../lib/transportDetection.js\";\n\nexport type AuthType =\n | \"oauth_dcr_not_supported\"\n | \"oauth_dcr\"\n | \"oauth_pre_registered\"\n | \"probe_failed\"\n | \"public\";\n\nexport interface ProbeInput {\n servers: Array<{ url: string }>;\n}\n\nexport interface ProbeOptions {\n /**\n * Maximum number of retries on transient pre-DCR network errors, on top of\n * the initial attempt. So `maxRetries=1` means up to 2 total attempts per\n * server. Defaults to 1.\n *\n * Retries fire only when the result is `network_error` AND no auth server\n * was discovered yet (i.e. POST initialize failed or returned a non-2xx\n * non-401 status). DCR network failures do NOT retry — they include the\n * discovered `authServer` in the result, which the retry filter excludes.\n * This prevents the rare case where a network blip after the DCR POST\n * was sent could cause duplicate orphan client registrations at the vendor.\n */\n maxRetries?: number;\n /** Per-server wall-clock timeout covering all HTTP calls for that server. */\n perServerTimeoutMs?: number;\n /** Delay between retry attempts. Defaults to 200ms. */\n retryDelayMs?: number;\n}\n\nexport interface ProbeOutput {\n results: ProbeResult[];\n}\n\nexport type ProbeReason =\n | \"auth_metadata_discovery_failed\"\n | \"dcr_rejected\"\n | \"dcr_success\"\n | \"network_error\"\n | \"no_auth_metadata\"\n | \"no_auth_required\"\n | \"no_registration_endpoint\"\n | \"pre_registered_provider\"\n | \"probe_timeout\";\n\nexport interface ProbeResult {\n authServer?: string;\n authType: AuthType;\n errorDetail?: string;\n httpStatus?: number;\n reason: ProbeReason;\n /**\n * For transient `dcr_rejected` results (429/5xx), the server's\n * `Retry-After` value in milliseconds, when provided. The retry wrapper\n * uses this as the inter-attempt delay; callers don't normally read it.\n */\n retryAfterMs?: number;\n url: string;\n}\n\n/**\n * The probe re-runs the same pre-browser steps as `performOAuthFlow` in\n * `oauthFlow.ts` — same SDK calls, same order — so we classify servers using\n * the exact code path the real OAuth flow would take. We stop just before the\n * browser-consent step (step 9+ in performOAuthFlow) because the probe runs\n * non-interactively at install time.\n *\n * Flow parity with performOAuthFlow:\n * - POST initialize (probe-specific: classify 200 vs 401 vs other)\n * - findProviderForUrl — same as performOAuthFlow step 2\n * - discoverOAuthProtectedResourceMetadata — same as step 3\n * - pick authorization_servers[0] with fallback — same as step 4\n * - discoverAuthorizationServerMetadata — same as step 5\n * - check registration_endpoint — same as step 7 precondition\n * - registerClient (SDK) — same as step 7\n * - return authType verdict (probe-only — OAuth flow would open browser here)\n *\n * authType mapping (kept alongside `reason` for callers that want diagnostics):\n * no_auth_required → public\n * pre_registered_provider → oauth_pre_registered\n * dcr_success → oauth_dcr\n * dcr_rejected → oauth_dcr_not_supported\n * no_registration_endpoint → oauth_dcr_not_supported\n * no_auth_metadata → oauth_dcr_not_supported\n * network_error → probe_failed\n */\n\nconst DCR_REDIRECT_URI = \"http://localhost:0/callback\";\nconst DEFAULT_PER_SERVER_TIMEOUT_MS = 15_000;\nconst DEFAULT_MAX_RETRIES = 1;\nconst DEFAULT_RETRY_DELAY_MS = 200;\n/**\n * Cap on `Retry-After` we'll honor before falling back to the default delay.\n * Prevents a misconfigured (or hostile) vendor from parking the install for\n * minutes/hours by setting `Retry-After: 3600`.\n */\nconst MAX_RETRY_AFTER_MS = 5_000;\n\nexport async function runProbeBatch(input: ProbeInput, options: ProbeOptions = {}): Promise<ProbeOutput> {\n const timeoutMs = options.perServerTimeoutMs ?? DEFAULT_PER_SERVER_TIMEOUT_MS;\n const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n\n const results = await Promise.all(\n input.servers.map((srv) => probeOneWithRetry(srv.url, timeoutMs, maxRetries, retryDelayMs))\n );\n\n return { results };\n}\n\n/**\n * Attempts DCR directly via fetch rather than SDK's `registerClient`.\n *\n * Reason we don't use the SDK here specifically: `registerClient` consumes the\n * response and throws, dropping the numeric HTTP status on success-with-bad-body\n * and on 4xx with a well-formed OAuth error body (e.g. Airtable). Probe needs\n * the status code for monitoring and to distinguish dcr_rejected from\n * network_error precisely. Everything else (discovery of resource and auth\n * server metadata) still goes through the SDK.\n *\n * Returns:\n * - { status, body } on 2xx with parseable JSON → caller classifies dcr_success\n * - { status, errorBody? } on non-2xx → caller classifies dcr_rejected\n * - throws on network failure/timeout → caller classifies network_error\n */\nasync function attemptDcr(\n registrationEndpoint: string,\n clientMetadata: OAuthClientMetadata,\n signal: AbortSignal\n): Promise<{\n body?: Record<string, unknown>;\n errorBody?: string;\n retryAfterMs?: number;\n status: number;\n}> {\n const res = await fetch(registrationEndpoint, {\n body: JSON.stringify(clientMetadata),\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n\n if (res.status === 200 || res.status === 201) {\n try {\n const body = (await res.json()) as Record<string, unknown>;\n // RFC 7591 §3.2.1 requires `client_id` in a successful registration\n // response. Some servers return a 2xx with a JSON error envelope or\n // a partial/malformed body; treating those as success would\n // false-positive `oauth_dcr` even though the OAuth flow can't\n // proceed. Require the mandatory field before classifying success.\n if (typeof body.client_id !== \"string\" || body.client_id.length === 0) {\n return { status: res.status };\n }\n return { body, status: res.status };\n } catch {\n // 2xx with unparseable body — caller treats as failure.\n return { status: res.status };\n }\n }\n\n // Non-2xx — try to surface the error body to errorDetail for humans.\n let errorBody: string | undefined;\n try {\n errorBody = (await res.text()).trim();\n } catch {\n // ignore\n }\n\n // Capture Retry-After (RFC 7231) on rate-limit / server-error responses so\n // probeOneWithRetry can wait the requested interval before re-attempting.\n // Anything outside the transient class (429 / 5xx) doesn't need this — we\n // won't retry those anyway.\n let retryAfterMs: number | undefined;\n if (res.status === 429 || res.status >= 500) {\n retryAfterMs = parseRetryAfter(res.headers.get(\"Retry-After\"));\n }\n\n return { errorBody, retryAfterMs, status: res.status };\n}\n\n/**\n * Performs the per-transport liveness/auth probe, falling back from Streamable\n * HTTP to SSE on 404/405 (the same priority order the runtime proxy uses via\n * `connectWithTransportFallback`). Returns the first response whose status is\n * not \"transport not supported\"; throws on any non-fallback error.\n *\n * The response body is cancelled before returning — the probe classifies on\n * `status` only and never reads body or headers. For SSE 200 responses this is\n * load-bearing: the event stream stays open indefinitely otherwise, leaking\n * connections at batch scale.\n */\nasync function attemptInitialize(url: string, signal: AbortSignal): Promise<Response> {\n const { result } = await walkTransports(async (transportType) => {\n const response =\n transportType === \"streamable-http\"\n ? await postInitialize(url, signal)\n : await getSseHandshake(url, signal);\n // Probe never reads body — cancel to avoid leaking SSE streams on 200.\n response.body?.cancel().catch(() => {\n /* already closed */\n });\n if (response.status === 404 || response.status === 405) {\n // Throw a status-bearing error so walkTransports' isTransportNotSupportedError\n // check matches and falls through to the next transport.\n throw Object.assign(new Error(`${transportType} returned ${response.status}`), {\n status: response.status,\n });\n }\n return response;\n });\n return result;\n}\n\nfunction clampRetryAfter(ms: number): number {\n if (ms <= 0) return 0;\n return Math.min(ms, MAX_RETRY_AFTER_MS);\n}\n\nfunction errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n/** Parses an OAuth error body (RFC 6749) into a human-friendly one-liner. */\nfunction formatDcrErrorBody(body: string | undefined): string | undefined {\n if (!body) return undefined;\n try {\n const parsed = JSON.parse(body) as { error?: string; error_description?: string };\n if (parsed.error_description) return parsed.error_description;\n if (parsed.error) return parsed.error;\n } catch {\n // Non-JSON body — return as-is, capped to avoid dumping HTML pages.\n }\n return body.length > 200 ? `${body.slice(0, 200)}...` : body;\n}\n\nasync function getSseHandshake(url: string, signal: AbortSignal): Promise<Response> {\n return fetch(url, {\n headers: { Accept: \"text/event-stream\" },\n method: \"GET\",\n signal,\n });\n}\n\nfunction isRetryableResult(result: ProbeResult): boolean {\n // Pre-DCR network error — fetch threw before discovery finished.\n if (result.reason === \"network_error\" && !result.authServer) return true;\n // DCR returned a transient HTTP status — server responded but can't help yet.\n if (result.reason === \"dcr_rejected\" && isTransientStatus(result.httpStatus)) return true;\n return false;\n}\n\nfunction isTransientStatus(status: number | undefined): boolean {\n if (!status) return false;\n if (status === 429) return true;\n return status >= 500 && status < 600;\n}\n\n/**\n * Parses the Retry-After header (RFC 7231) in either of its two forms:\n * - delta-seconds: \"120\"\n * - HTTP-date: \"Wed, 21 Oct 2026 07:28:00 GMT\"\n *\n * Caps the result at MAX_RETRY_AFTER_MS so a misconfigured / malicious\n * server can't park our install for an hour. Returns undefined for\n * missing/unparseable values; callers fall back to the default delay.\n */\nfunction parseRetryAfter(header: null | string): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n if (!trimmed) return undefined;\n\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) {\n return clampRetryAfter(asNumber * 1000);\n }\n\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) {\n const ms = asDate - Date.now();\n return ms > 0 ? clampRetryAfter(ms) : 0;\n }\n\n return undefined;\n}\n\nasync function postInitialize(url: string, signal: AbortSignal): Promise<Response> {\n return fetch(url, {\n body: JSON.stringify({\n id: 1,\n jsonrpc: \"2.0\",\n method: \"initialize\",\n params: {\n capabilities: {},\n clientInfo: { name: \"mcp-gateway-probe\", version: \"1.0\" },\n protocolVersion: \"2024-11-05\",\n },\n }),\n headers: {\n Accept: \"application/json, text/event-stream\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n}\n\nasync function probeOne(url: string, signal: AbortSignal): Promise<ProbeResult> {\n const serverUrlObj = new URL(url);\n\n // Step 0: pre-configured OAuth provider — short-circuit before any network\n // call. OAUTH_PROVIDERS holds servers we've baked credentials into the\n // gateway for at build time; if a URL matches, we already know it needs\n // OAuth and we already have credentials, so probing the server itself\n // is wasted work.\n //\n // performOAuthFlow does this check at its step 2 (after starting a callback\n // server), but the probe never opens a browser, so we can hoist it earlier\n // and avoid the network calls oauthFlow's structure forces.\n if (findProviderForUrl(serverUrlObj)) {\n return { authType: \"oauth_pre_registered\", reason: \"pre_registered_provider\", url };\n }\n\n // Step 1: liveness/auth probe with transport fallback (Streamable HTTP → SSE,\n // matching the runtime proxy's priority order). Classify:\n // 200 → wrap (no_auth_required)\n // 401 → continue with auth discovery (same path performOAuthFlow takes)\n // else → skip (network_error)\n // attemptInitialize walks transports via walkTransports and falls through\n // 404/405 — so a server like cf-docs (POST /sse 404, GET /sse 200) classifies\n // as public on the SSE attempt rather than failing on the streamable-HTTP one.\n let initResponse: Response;\n try {\n initResponse = await attemptInitialize(url, signal);\n } catch (err) {\n return { authType: \"probe_failed\", errorDetail: errMsg(err), reason: \"network_error\", url };\n }\n if (initResponse.ok) {\n return { authType: \"public\", reason: \"no_auth_required\", url };\n }\n if (initResponse.status !== 401) {\n return {\n authType: \"probe_failed\",\n errorDetail: `initialize returned status ${initResponse.status}`,\n httpStatus: initResponse.status,\n reason: \"network_error\",\n url,\n };\n }\n\n // Steps 3-5: shared discovery with performOAuthFlow — see ../auth/discovery.ts.\n // The helper performs resource-metadata lookup, auth-server-URL selection, and\n // auth-server-metadata lookup in that order. It silences resource-metadata\n // errors (soft-fail) but throws AuthServerDiscoveryError when the auth-server\n // metadata call fails — preserving the computed authServerUrl on the error.\n let authMetadata: Awaited<ReturnType<typeof discoverAuthServer>>[\"authMetadata\"];\n let authServerUrl: URL;\n try {\n // Pass the per-server signal so a probeOneWithTimeout abort cancels the\n // SDK's well-known fetches too — otherwise orphaned requests outlive\n // the probe verdict and leak connections in batch runs.\n const discovered = await discoverAuthServer(serverUrlObj, { signal });\n authMetadata = discovered.authMetadata;\n authServerUrl = discovered.authServerUrl;\n } catch (err) {\n const authServer =\n err instanceof AuthServerDiscoveryError ? err.authServerUrl.toString() : undefined;\n // Thrown errors here are transport failures (DNS/timeout/5xx) on the\n // auth-server metadata fetch, NOT the \"metadata is genuinely absent\"\n // case. Folding them into oauth_dcr_not_supported would let the\n // server-side cache persist a transient outage as a permanent\n // negative verdict. Surface as probe_failed instead so the scanner\n // filter drops it from the cache write (transient state stays\n // transient). The definitive metadata-absent path lives in the\n // !authMetadata branch below.\n return {\n authServer,\n authType: \"probe_failed\",\n errorDetail: errMsg(err),\n reason: \"auth_metadata_discovery_failed\",\n url,\n };\n }\n if (!authMetadata) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n reason: \"no_auth_metadata\",\n url,\n };\n }\n\n // Step 7 precondition: registration_endpoint present?\n // (performOAuthFlow throws here; probe classifies as oauth_dcr_not_supported instead.)\n if (!authMetadata.registration_endpoint) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n reason: \"no_registration_endpoint\",\n url,\n };\n }\n\n // Step 7: DCR. Same body/method as performOAuthFlow, but attemptDcr gives us\n // the raw status code so we can distinguish dcr_rejected (4xx/5xx) from\n // network_error (fetch throw) and report httpStatus for monitoring.\n //\n // client_name is sourced from the same `CLIENT_APP_NAME` env the runtime\n // OAuth flow reads (see performOAuthFlow / getDcrClientName) so that\n // allowlist-style DCR endpoints (e.g. Figma) give the probe the same\n // verdict the runtime flow would produce for this agent. Without this,\n // probe would always send \"MCP Gateway\" and false-classify Figma as\n // oauth_dcr_not_supported even though a Cursor/Code/Copilot install\n // would succeed.\n // client_uri, like client_name, is sourced from CLIENT_APP_NAME so the probe\n // sends the same payload the runtime flow would. Some allowlist-style DCR\n // endpoints (e.g. Figma for VS Code) gate on client_uri; omitted when the\n // current app has none so other agents' probe payloads are unchanged.\n const clientUri = getDcrClientUri();\n const clientMetadata: OAuthClientMetadata = {\n client_name: getDcrClientName(),\n ...(clientUri && { client_uri: clientUri }),\n grant_types: [\"authorization_code\", \"refresh_token\"],\n // Per-(agent, server-host) decoy URI may be prepended at index 0 to pass\n // allowlist-style DCR gates (see DECOY_REDIRECT_URI_BY_APP_AND_HOST in\n // auth/oauthFlow.ts). For most pairs this resolves to [DCR_REDIRECT_URI],\n // preserving the pre-existing probe shape exactly.\n redirect_uris: getDcrRedirectUris(serverUrlObj, DCR_REDIRECT_URI),\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n };\n let dcr: Awaited<ReturnType<typeof attemptDcr>>;\n try {\n dcr = await attemptDcr(authMetadata.registration_endpoint, clientMetadata, signal);\n } catch (err) {\n // fetch itself threw — network layer failure, not a policy decision\n // from the auth server.\n return {\n authServer: authServerUrl.toString(),\n authType: \"probe_failed\",\n errorDetail: errMsg(err),\n reason: \"network_error\",\n url,\n };\n }\n\n if (dcr.status !== 200 && dcr.status !== 201) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n errorDetail: formatDcrErrorBody(dcr.errorBody),\n httpStatus: dcr.status,\n reason: \"dcr_rejected\",\n retryAfterMs: dcr.retryAfterMs,\n url,\n };\n }\n if (!dcr.body) {\n // 2xx but body didn't parse — treat as rejection rather than silently wrap.\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n errorDetail: `DCR returned ${dcr.status} with unparseable body`,\n httpStatus: dcr.status,\n reason: \"dcr_rejected\",\n url,\n };\n }\n\n // NOTE: performOAuthFlow would open the browser and complete the flow here.\n // The probe stops at successful DCR.\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr\",\n reason: \"dcr_success\",\n url,\n };\n}\n\n/**\n * Wraps `probeOneWithTimeout` with retry-on-transient-error.\n *\n * Retries up to `maxRetries` times when the result is transient. Two\n * categories of transient are recognized:\n *\n * 1. Pre-DCR network error — `reason === \"network_error\" && !authServer`.\n * The fetch threw or returned non-401/non-2xx before discovery\n * finished. No registration request reached any vendor; retrying is\n * structurally safe (no orphan multiplication).\n *\n * 2. DCR transient — `reason === \"dcr_rejected\" && (httpStatus === 429\n * || httpStatus >= 500)`. The vendor responded definitively that they\n * can't help right now (rate-limited or server error). Because we got\n * a complete response, the server explicitly did NOT create a\n * registration; retrying is also safe and may succeed once the\n * transient condition clears.\n *\n * Notably NOT retried:\n * - DCR network failures (`network_error` WITH `authServer`) — fetch\n * threw mid-flight; the request may have arrived at the vendor.\n * - DCR 4xx (other than 429) — definitive policy refusal.\n * - `no_auth_metadata`, `no_registration_endpoint` — definitive answers.\n *\n * For DCR transients, the actual delay is `max(retryDelayMs, retryAfterMs)`\n * if the server provided a `Retry-After` header (capped to MAX_RETRY_AFTER_MS).\n */\nasync function probeOneWithRetry(\n url: string,\n timeoutMs: number,\n maxRetries: number,\n retryDelayMs: number\n): Promise<ProbeResult> {\n let result = await probeOneWithTimeout(url, timeoutMs);\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n if (!isRetryableResult(result)) return result;\n const delay = Math.max(retryDelayMs, result.retryAfterMs ?? 0);\n if (delay > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n }\n result = await probeOneWithTimeout(url, timeoutMs);\n }\n return result;\n}\n\nasync function probeOneWithTimeout(url: string, timeoutMs: number): Promise<ProbeResult> {\n const controller = new AbortController();\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n // Race the probe against a wall-clock timeout. AbortSignal alone isn't\n // enough — some fetch implementations (or test mocks) may ignore it. This\n // guarantees we always return within timeoutMs.\n const timeoutPromise = new Promise<ProbeResult>((resolve) => {\n timerId = setTimeout(() => {\n controller.abort();\n // Distinct reason \"probe_timeout\" — NOT \"network_error\". The\n // wall-clock timeout fires from outside probeOne, so we don't\n // know which phase aborted: discovery, registration POST, or\n // anything in between. If the timeout struck after the\n // registration POST went through, retrying would create a second\n // DCR client_id. Marking timeouts non-retryable (see\n // isRetryableResult) errs on the side of one orphan probe over\n // duplicate DCR registrations.\n resolve({\n authType: \"probe_failed\",\n errorDetail: `probe timed out after ${timeoutMs}ms`,\n reason: \"probe_timeout\",\n url,\n });\n }, timeoutMs);\n });\n\n const probePromise = probeOne(url, controller.signal).catch((err) => ({\n authType: \"probe_failed\" as const,\n errorDetail: controller.signal.aborted ? `probe timed out after ${timeoutMs}ms` : errMsg(err),\n // controller.signal.aborted means the wall-clock timeoutPromise\n // fired and aborted us mid-flight. Same retry-safety reasoning as\n // the timeoutPromise branch — surface as probe_timeout so we\n // don't reissue DCR.\n reason: controller.signal.aborted ? (\"probe_timeout\" as const) : (\"network_error\" as const),\n url,\n }));\n\n try {\n return await Promise.race([probePromise, timeoutPromise]);\n } finally {\n if (timerId) clearTimeout(timerId);\n }\n}\n","import type { ProbeInput } from \"./index.js\";\n\nimport { runProbeBatch } from \"./index.js\";\n\nconst EXIT_OK = 0;\nconst EXIT_BAD_INPUT = 2;\n\n/**\n * Entry point for the `mcp-gateway probe` subcommand.\n *\n * Reads a JSON batch of server URLs from stdin, runs the DCR/auth probe for\n * each in parallel, and writes the aggregated result JSON to stdout.\n *\n * Intended to be invoked by the scanner during install to decide which remote\n * MCP servers are safe to wrap vs. leave alone.\n */\nexport async function runProbeCli(): Promise<number> {\n let raw: string;\n try {\n raw = await readStdin();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`probe: failed to read stdin: ${msg}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`probe: stdin was not valid JSON: ${msg}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n if (!isValidInput(parsed)) {\n process.stderr.write(`probe: invalid input — expected {\"servers\":[{\"url\":\"...\"}]}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n const output = await runProbeBatch(parsed);\n process.stdout.write(`${JSON.stringify(output)}\\n`);\n return EXIT_OK;\n}\n\nfunction isValidInput(value: unknown): value is ProbeInput {\n if (!value || typeof value !== \"object\") return false;\n const servers = (value as { servers?: unknown }).servers;\n if (!Array.isArray(servers)) return false;\n return servers.every((s) => s && typeof s === \"object\" && typeof (s as { url?: unknown }).url === \"string\");\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli-C3ziJuw5.js","names":["errorBody: string | undefined","retryAfterMs: number | undefined","initResponse: Response","authMetadata: Awaited<ReturnType<typeof discoverAuthServer>>[\"authMetadata\"]","authServerUrl: URL","clientMetadata: OAuthClientMetadata","dcr: Awaited<ReturnType<typeof attemptDcr>>","timerId: ReturnType<typeof setTimeout> | undefined","raw: string","parsed: unknown","chunks: Buffer[]"],"sources":["../src/probe/index.ts","../src/probe/cli.ts"],"sourcesContent":["import type { OAuthClientMetadata } from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nimport { AuthServerDiscoveryError, discoverAuthServer } from \"../auth/discovery.js\";\nimport { getDcrClientName, getDcrClientUri, getDcrRedirectUris } from \"../auth/oauthFlow.js\";\nimport { findProviderForUrl } from \"../auth/providers.js\";\nimport { walkTransports } from \"../lib/transportDetection.js\";\n\nexport type AuthType =\n | \"oauth_dcr_not_supported\"\n | \"oauth_dcr\"\n | \"oauth_pre_registered\"\n | \"probe_failed\"\n | \"public\";\n\nexport interface ProbeInput {\n servers: Array<{ url: string }>;\n}\n\nexport interface ProbeOptions {\n /**\n * Maximum number of retries on transient pre-DCR network errors, on top of\n * the initial attempt. So `maxRetries=1` means up to 2 total attempts per\n * server. Defaults to 1.\n *\n * Retries fire only when the result is `network_error` AND no auth server\n * was discovered yet (i.e. POST initialize failed or returned a non-2xx\n * non-401 status). DCR network failures do NOT retry — they include the\n * discovered `authServer` in the result, which the retry filter excludes.\n * This prevents the rare case where a network blip after the DCR POST\n * was sent could cause duplicate orphan client registrations at the vendor.\n */\n maxRetries?: number;\n /** Per-server wall-clock timeout covering all HTTP calls for that server. */\n perServerTimeoutMs?: number;\n /** Delay between retry attempts. Defaults to 200ms. */\n retryDelayMs?: number;\n}\n\nexport interface ProbeOutput {\n results: ProbeResult[];\n}\n\nexport type ProbeReason =\n | \"auth_metadata_discovery_failed\"\n | \"dcr_rejected\"\n | \"dcr_success\"\n | \"network_error\"\n | \"no_auth_metadata\"\n | \"no_auth_required\"\n | \"no_registration_endpoint\"\n | \"pre_registered_provider\"\n | \"probe_timeout\";\n\nexport interface ProbeResult {\n authServer?: string;\n authType: AuthType;\n errorDetail?: string;\n httpStatus?: number;\n reason: ProbeReason;\n /**\n * For transient `dcr_rejected` results (429/5xx), the server's\n * `Retry-After` value in milliseconds, when provided. The retry wrapper\n * uses this as the inter-attempt delay; callers don't normally read it.\n */\n retryAfterMs?: number;\n url: string;\n}\n\n/**\n * The probe re-runs the same pre-browser steps as `performOAuthFlow` in\n * `oauthFlow.ts` — same SDK calls, same order — so we classify servers using\n * the exact code path the real OAuth flow would take. We stop just before the\n * browser-consent step (step 9+ in performOAuthFlow) because the probe runs\n * non-interactively at install time.\n *\n * Flow parity with performOAuthFlow:\n * - POST initialize (probe-specific: classify 200 vs 401 vs other)\n * - findProviderForUrl — same as performOAuthFlow step 2\n * - discoverOAuthProtectedResourceMetadata — same as step 3\n * - pick authorization_servers[0] with fallback — same as step 4\n * - discoverAuthorizationServerMetadata — same as step 5\n * - check registration_endpoint — same as step 7 precondition\n * - registerClient (SDK) — same as step 7\n * - return authType verdict (probe-only — OAuth flow would open browser here)\n *\n * authType mapping (kept alongside `reason` for callers that want diagnostics):\n * no_auth_required → public\n * pre_registered_provider → oauth_pre_registered\n * dcr_success → oauth_dcr\n * dcr_rejected → oauth_dcr_not_supported\n * no_registration_endpoint → oauth_dcr_not_supported\n * no_auth_metadata → oauth_dcr_not_supported\n * network_error → probe_failed\n */\n\nconst DCR_REDIRECT_URI = \"http://localhost:0/callback\";\nconst DEFAULT_PER_SERVER_TIMEOUT_MS = 15_000;\nconst DEFAULT_MAX_RETRIES = 1;\nconst DEFAULT_RETRY_DELAY_MS = 200;\n/**\n * Cap on `Retry-After` we'll honor before falling back to the default delay.\n * Prevents a misconfigured (or hostile) vendor from parking the install for\n * minutes/hours by setting `Retry-After: 3600`.\n */\nconst MAX_RETRY_AFTER_MS = 5_000;\n\nexport async function runProbeBatch(input: ProbeInput, options: ProbeOptions = {}): Promise<ProbeOutput> {\n const timeoutMs = options.perServerTimeoutMs ?? DEFAULT_PER_SERVER_TIMEOUT_MS;\n const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n\n const results = await Promise.all(\n input.servers.map((srv) => probeOneWithRetry(srv.url, timeoutMs, maxRetries, retryDelayMs))\n );\n\n return { results };\n}\n\n/**\n * Attempts DCR directly via fetch rather than SDK's `registerClient`.\n *\n * Reason we don't use the SDK here specifically: `registerClient` consumes the\n * response and throws, dropping the numeric HTTP status on success-with-bad-body\n * and on 4xx with a well-formed OAuth error body (e.g. Airtable). Probe needs\n * the status code for monitoring and to distinguish dcr_rejected from\n * network_error precisely. Everything else (discovery of resource and auth\n * server metadata) still goes through the SDK.\n *\n * Returns:\n * - { status, body } on 2xx with parseable JSON → caller classifies dcr_success\n * - { status, errorBody? } on non-2xx → caller classifies dcr_rejected\n * - throws on network failure/timeout → caller classifies network_error\n */\nasync function attemptDcr(\n registrationEndpoint: string,\n clientMetadata: OAuthClientMetadata,\n signal: AbortSignal\n): Promise<{\n body?: Record<string, unknown>;\n errorBody?: string;\n retryAfterMs?: number;\n status: number;\n}> {\n const res = await fetch(registrationEndpoint, {\n body: JSON.stringify(clientMetadata),\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n\n if (res.status === 200 || res.status === 201) {\n try {\n const body = (await res.json()) as Record<string, unknown>;\n // RFC 7591 §3.2.1 requires `client_id` in a successful registration\n // response. Some servers return a 2xx with a JSON error envelope or\n // a partial/malformed body; treating those as success would\n // false-positive `oauth_dcr` even though the OAuth flow can't\n // proceed. Require the mandatory field before classifying success.\n if (typeof body.client_id !== \"string\" || body.client_id.length === 0) {\n return { status: res.status };\n }\n return { body, status: res.status };\n } catch {\n // 2xx with unparseable body — caller treats as failure.\n return { status: res.status };\n }\n }\n\n // Non-2xx — try to surface the error body to errorDetail for humans.\n let errorBody: string | undefined;\n try {\n errorBody = (await res.text()).trim();\n } catch {\n // ignore\n }\n\n // Capture Retry-After (RFC 7231) on rate-limit / server-error responses so\n // probeOneWithRetry can wait the requested interval before re-attempting.\n // Anything outside the transient class (429 / 5xx) doesn't need this — we\n // won't retry those anyway.\n let retryAfterMs: number | undefined;\n if (res.status === 429 || res.status >= 500) {\n retryAfterMs = parseRetryAfter(res.headers.get(\"Retry-After\"));\n }\n\n return { errorBody, retryAfterMs, status: res.status };\n}\n\n/**\n * Performs the per-transport liveness/auth probe, falling back from Streamable\n * HTTP to SSE on 404/405 (the same priority order the runtime proxy uses via\n * `connectWithTransportFallback`). Returns the first response whose status is\n * not \"transport not supported\"; throws on any non-fallback error.\n *\n * The response body is cancelled before returning — the probe classifies on\n * `status` only and never reads body or headers. For SSE 200 responses this is\n * load-bearing: the event stream stays open indefinitely otherwise, leaking\n * connections at batch scale.\n */\nasync function attemptInitialize(url: string, signal: AbortSignal): Promise<Response> {\n const { result } = await walkTransports(async (transportType) => {\n const response =\n transportType === \"streamable-http\"\n ? await postInitialize(url, signal)\n : await getSseHandshake(url, signal);\n // Probe never reads body — cancel to avoid leaking SSE streams on 200.\n response.body?.cancel().catch(() => {\n /* already closed */\n });\n if (response.status === 404 || response.status === 405) {\n // Throw a status-bearing error so walkTransports' isTransportNotSupportedError\n // check matches and falls through to the next transport.\n throw Object.assign(new Error(`${transportType} returned ${response.status}`), {\n status: response.status,\n });\n }\n return response;\n });\n return result;\n}\n\nfunction clampRetryAfter(ms: number): number {\n if (ms <= 0) return 0;\n return Math.min(ms, MAX_RETRY_AFTER_MS);\n}\n\nfunction errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n/** Parses an OAuth error body (RFC 6749) into a human-friendly one-liner. */\nfunction formatDcrErrorBody(body: string | undefined): string | undefined {\n if (!body) return undefined;\n try {\n const parsed = JSON.parse(body) as { error?: string; error_description?: string };\n if (parsed.error_description) return parsed.error_description;\n if (parsed.error) return parsed.error;\n } catch {\n // Non-JSON body — return as-is, capped to avoid dumping HTML pages.\n }\n return body.length > 200 ? `${body.slice(0, 200)}...` : body;\n}\n\nasync function getSseHandshake(url: string, signal: AbortSignal): Promise<Response> {\n return fetch(url, {\n headers: { Accept: \"text/event-stream\" },\n method: \"GET\",\n signal,\n });\n}\n\nfunction isRetryableResult(result: ProbeResult): boolean {\n // Pre-DCR network error — fetch threw before discovery finished.\n if (result.reason === \"network_error\" && !result.authServer) return true;\n // DCR returned a transient HTTP status — server responded but can't help yet.\n if (result.reason === \"dcr_rejected\" && isTransientStatus(result.httpStatus)) return true;\n return false;\n}\n\nfunction isTransientStatus(status: number | undefined): boolean {\n if (!status) return false;\n if (status === 429) return true;\n return status >= 500 && status < 600;\n}\n\n/**\n * Parses the Retry-After header (RFC 7231) in either of its two forms:\n * - delta-seconds: \"120\"\n * - HTTP-date: \"Wed, 21 Oct 2026 07:28:00 GMT\"\n *\n * Caps the result at MAX_RETRY_AFTER_MS so a misconfigured / malicious\n * server can't park our install for an hour. Returns undefined for\n * missing/unparseable values; callers fall back to the default delay.\n */\nfunction parseRetryAfter(header: null | string): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n if (!trimmed) return undefined;\n\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) {\n return clampRetryAfter(asNumber * 1000);\n }\n\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) {\n const ms = asDate - Date.now();\n return ms > 0 ? clampRetryAfter(ms) : 0;\n }\n\n return undefined;\n}\n\nasync function postInitialize(url: string, signal: AbortSignal): Promise<Response> {\n return fetch(url, {\n body: JSON.stringify({\n id: 1,\n jsonrpc: \"2.0\",\n method: \"initialize\",\n params: {\n capabilities: {},\n clientInfo: { name: \"mcp-gateway-probe\", version: \"1.0\" },\n protocolVersion: \"2024-11-05\",\n },\n }),\n headers: {\n Accept: \"application/json, text/event-stream\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n}\n\nasync function probeOne(url: string, signal: AbortSignal): Promise<ProbeResult> {\n const serverUrlObj = new URL(url);\n\n // Step 0: pre-configured OAuth provider — short-circuit before any network\n // call. OAUTH_PROVIDERS holds servers we've baked credentials into the\n // gateway for at build time; if a URL matches, we already know it needs\n // OAuth and we already have credentials, so probing the server itself\n // is wasted work.\n //\n // performOAuthFlow does this check at its step 2 (after starting a callback\n // server), but the probe never opens a browser, so we can hoist it earlier\n // and avoid the network calls oauthFlow's structure forces.\n if (findProviderForUrl(serverUrlObj)) {\n return { authType: \"oauth_pre_registered\", reason: \"pre_registered_provider\", url };\n }\n\n // Step 1: liveness/auth probe with transport fallback (Streamable HTTP → SSE,\n // matching the runtime proxy's priority order). Classify:\n // 200 → wrap (no_auth_required)\n // 401 → continue with auth discovery (same path performOAuthFlow takes)\n // else → skip (network_error)\n // attemptInitialize walks transports via walkTransports and falls through\n // 404/405 — so a server like cf-docs (POST /sse 404, GET /sse 200) classifies\n // as public on the SSE attempt rather than failing on the streamable-HTTP one.\n let initResponse: Response;\n try {\n initResponse = await attemptInitialize(url, signal);\n } catch (err) {\n return { authType: \"probe_failed\", errorDetail: errMsg(err), reason: \"network_error\", url };\n }\n if (initResponse.ok) {\n return { authType: \"public\", reason: \"no_auth_required\", url };\n }\n if (initResponse.status !== 401) {\n return {\n authType: \"probe_failed\",\n errorDetail: `initialize returned status ${initResponse.status}`,\n httpStatus: initResponse.status,\n reason: \"network_error\",\n url,\n };\n }\n\n // Steps 3-5: shared discovery with performOAuthFlow — see ../auth/discovery.ts.\n // The helper performs resource-metadata lookup, auth-server-URL selection, and\n // auth-server-metadata lookup in that order. It silences resource-metadata\n // errors (soft-fail) but throws AuthServerDiscoveryError when the auth-server\n // metadata call fails — preserving the computed authServerUrl on the error.\n let authMetadata: Awaited<ReturnType<typeof discoverAuthServer>>[\"authMetadata\"];\n let authServerUrl: URL;\n try {\n // Pass the per-server signal so a probeOneWithTimeout abort cancels the\n // SDK's well-known fetches too — otherwise orphaned requests outlive\n // the probe verdict and leak connections in batch runs.\n const discovered = await discoverAuthServer(serverUrlObj, { signal });\n authMetadata = discovered.authMetadata;\n authServerUrl = discovered.authServerUrl;\n } catch (err) {\n const authServer =\n err instanceof AuthServerDiscoveryError ? err.authServerUrl.toString() : undefined;\n // Thrown errors here are transport failures (DNS/timeout/5xx) on the\n // auth-server metadata fetch, NOT the \"metadata is genuinely absent\"\n // case. Folding them into oauth_dcr_not_supported would let the\n // server-side cache persist a transient outage as a permanent\n // negative verdict. Surface as probe_failed instead so the scanner\n // filter drops it from the cache write (transient state stays\n // transient). The definitive metadata-absent path lives in the\n // !authMetadata branch below.\n return {\n authServer,\n authType: \"probe_failed\",\n errorDetail: errMsg(err),\n reason: \"auth_metadata_discovery_failed\",\n url,\n };\n }\n if (!authMetadata) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n reason: \"no_auth_metadata\",\n url,\n };\n }\n\n // Step 7 precondition: registration_endpoint present?\n // (performOAuthFlow throws here; probe classifies as oauth_dcr_not_supported instead.)\n if (!authMetadata.registration_endpoint) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n reason: \"no_registration_endpoint\",\n url,\n };\n }\n\n // Step 7: DCR. Same body/method as performOAuthFlow, but attemptDcr gives us\n // the raw status code so we can distinguish dcr_rejected (4xx/5xx) from\n // network_error (fetch throw) and report httpStatus for monitoring.\n //\n // client_name is sourced from the same `CLIENT_APP_NAME` env the runtime\n // OAuth flow reads (see performOAuthFlow / getDcrClientName) so that\n // allowlist-style DCR endpoints (e.g. Figma) give the probe the same\n // verdict the runtime flow would produce for this agent. Without this,\n // probe would always send \"MCP Gateway\" and false-classify Figma as\n // oauth_dcr_not_supported even though a Cursor/Code/Copilot install\n // would succeed.\n // client_uri, like client_name, is sourced from CLIENT_APP_NAME so the probe\n // sends the same payload the runtime flow would. Some allowlist-style DCR\n // endpoints (e.g. Figma for VS Code) gate on client_uri; omitted when the\n // current app has none so other agents' probe payloads are unchanged.\n const clientUri = getDcrClientUri();\n const clientMetadata: OAuthClientMetadata = {\n client_name: getDcrClientName(),\n ...(clientUri && { client_uri: clientUri }),\n grant_types: [\"authorization_code\", \"refresh_token\"],\n // Per-(agent, server-host) decoy URI may be prepended at index 0 to pass\n // allowlist-style DCR gates (see DECOY_REDIRECT_URI_BY_APP_AND_HOST in\n // auth/oauthFlow.ts). For most pairs this resolves to [DCR_REDIRECT_URI],\n // preserving the pre-existing probe shape exactly.\n redirect_uris: getDcrRedirectUris(serverUrlObj, DCR_REDIRECT_URI),\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n };\n let dcr: Awaited<ReturnType<typeof attemptDcr>>;\n try {\n dcr = await attemptDcr(authMetadata.registration_endpoint, clientMetadata, signal);\n } catch (err) {\n // fetch itself threw — network layer failure, not a policy decision\n // from the auth server.\n return {\n authServer: authServerUrl.toString(),\n authType: \"probe_failed\",\n errorDetail: errMsg(err),\n reason: \"network_error\",\n url,\n };\n }\n\n if (dcr.status !== 200 && dcr.status !== 201) {\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n errorDetail: formatDcrErrorBody(dcr.errorBody),\n httpStatus: dcr.status,\n reason: \"dcr_rejected\",\n retryAfterMs: dcr.retryAfterMs,\n url,\n };\n }\n if (!dcr.body) {\n // 2xx but body didn't parse — treat as rejection rather than silently wrap.\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr_not_supported\",\n errorDetail: `DCR returned ${dcr.status} with unparseable body`,\n httpStatus: dcr.status,\n reason: \"dcr_rejected\",\n url,\n };\n }\n\n // NOTE: performOAuthFlow would open the browser and complete the flow here.\n // The probe stops at successful DCR.\n return {\n authServer: authServerUrl.toString(),\n authType: \"oauth_dcr\",\n reason: \"dcr_success\",\n url,\n };\n}\n\n/**\n * Wraps `probeOneWithTimeout` with retry-on-transient-error.\n *\n * Retries up to `maxRetries` times when the result is transient. Two\n * categories of transient are recognized:\n *\n * 1. Pre-DCR network error — `reason === \"network_error\" && !authServer`.\n * The fetch threw or returned non-401/non-2xx before discovery\n * finished. No registration request reached any vendor; retrying is\n * structurally safe (no orphan multiplication).\n *\n * 2. DCR transient — `reason === \"dcr_rejected\" && (httpStatus === 429\n * || httpStatus >= 500)`. The vendor responded definitively that they\n * can't help right now (rate-limited or server error). Because we got\n * a complete response, the server explicitly did NOT create a\n * registration; retrying is also safe and may succeed once the\n * transient condition clears.\n *\n * Notably NOT retried:\n * - DCR network failures (`network_error` WITH `authServer`) — fetch\n * threw mid-flight; the request may have arrived at the vendor.\n * - DCR 4xx (other than 429) — definitive policy refusal.\n * - `no_auth_metadata`, `no_registration_endpoint` — definitive answers.\n *\n * For DCR transients, the actual delay is `max(retryDelayMs, retryAfterMs)`\n * if the server provided a `Retry-After` header (capped to MAX_RETRY_AFTER_MS).\n */\nasync function probeOneWithRetry(\n url: string,\n timeoutMs: number,\n maxRetries: number,\n retryDelayMs: number\n): Promise<ProbeResult> {\n let result = await probeOneWithTimeout(url, timeoutMs);\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n if (!isRetryableResult(result)) return result;\n const delay = Math.max(retryDelayMs, result.retryAfterMs ?? 0);\n if (delay > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n }\n result = await probeOneWithTimeout(url, timeoutMs);\n }\n return result;\n}\n\nasync function probeOneWithTimeout(url: string, timeoutMs: number): Promise<ProbeResult> {\n const controller = new AbortController();\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n // Race the probe against a wall-clock timeout. AbortSignal alone isn't\n // enough — some fetch implementations (or test mocks) may ignore it. This\n // guarantees we always return within timeoutMs.\n const timeoutPromise = new Promise<ProbeResult>((resolve) => {\n timerId = setTimeout(() => {\n controller.abort();\n // Distinct reason \"probe_timeout\" — NOT \"network_error\". The\n // wall-clock timeout fires from outside probeOne, so we don't\n // know which phase aborted: discovery, registration POST, or\n // anything in between. If the timeout struck after the\n // registration POST went through, retrying would create a second\n // DCR client_id. Marking timeouts non-retryable (see\n // isRetryableResult) errs on the side of one orphan probe over\n // duplicate DCR registrations.\n resolve({\n authType: \"probe_failed\",\n errorDetail: `probe timed out after ${timeoutMs}ms`,\n reason: \"probe_timeout\",\n url,\n });\n }, timeoutMs);\n });\n\n const probePromise = probeOne(url, controller.signal).catch((err) => ({\n authType: \"probe_failed\" as const,\n errorDetail: controller.signal.aborted ? `probe timed out after ${timeoutMs}ms` : errMsg(err),\n // controller.signal.aborted means the wall-clock timeoutPromise\n // fired and aborted us mid-flight. Same retry-safety reasoning as\n // the timeoutPromise branch — surface as probe_timeout so we\n // don't reissue DCR.\n reason: controller.signal.aborted ? (\"probe_timeout\" as const) : (\"network_error\" as const),\n url,\n }));\n\n try {\n return await Promise.race([probePromise, timeoutPromise]);\n } finally {\n if (timerId) clearTimeout(timerId);\n }\n}\n","import type { ProbeInput } from \"./index.js\";\n\nimport { runProbeBatch } from \"./index.js\";\n\nconst EXIT_OK = 0;\nconst EXIT_BAD_INPUT = 2;\n\n/**\n * Entry point for the `mcp-gateway probe` subcommand.\n *\n * Reads a JSON batch of server URLs from stdin, runs the DCR/auth probe for\n * each in parallel, and writes the aggregated result JSON to stdout.\n *\n * Intended to be invoked by the scanner during install to decide which remote\n * MCP servers are safe to wrap vs. leave alone.\n */\nexport async function runProbeCli(): Promise<number> {\n let raw: string;\n try {\n raw = await readStdin();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`probe: failed to read stdin: ${msg}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`probe: stdin was not valid JSON: ${msg}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n if (!isValidInput(parsed)) {\n process.stderr.write(`probe: invalid input — expected {\"servers\":[{\"url\":\"...\"}]}\\n`);\n return EXIT_BAD_INPUT;\n }\n\n const output = await runProbeBatch(parsed);\n process.stdout.write(`${JSON.stringify(output)}\\n`);\n return EXIT_OK;\n}\n\nfunction isValidInput(value: unknown): value is ProbeInput {\n if (!value || typeof value !== \"object\") return false;\n const servers = (value as { servers?: unknown }).servers;\n if (!Array.isArray(servers)) return false;\n return servers.every((s) => s && typeof s === \"object\" && typeof (s as { url?: unknown }).url === \"string\");\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- import{ACCESS_CONTROL_HEADERS as e,ACCESS_CONTROL_TIMEOUT_MS as t,ACCESS_CONTROL_URL as n,APP_VERSION as r,CLIENT_APP_NAME as i,DEBUG_MODE as a,LOG_DIR as o,LOG_INGEST_ENABLED as s,LOG_INGEST_TIMEOUT_MS as c,LOG_INGEST_URL as l,MIRROR_URL as u,OAUTH_DIR as d,OAUTH_PROVIDERS_TIMEOUT_MS as f,OAUTH_PROVIDERS_URL as p,PROXY_COMMAND as m,SCANNER_API_KEY as h,SCANNER_FAIL_OPEN as g,SCANNER_HEADERS as _,SCANNER_TIMEOUT_MS as v,SCANNER_URL as y,SESSION_ID as b,TOOL_CALL_MAX_TOTAL_TIMEOUT_MS as x,TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS as S,TOOL_CALL_TIMEOUT_MS as C,UPSTREAM_CONNECT_INITIAL_DELAY_MS as w,UPSTREAM_CONNECT_MAX_DELAY_MS as T,UPSTREAM_CONNECT_MAX_ELAPSED_MS as E,UPSTREAM_CONNECT_MAX_RETRIES as D,UPSTREAM_RECONNECT_COOLDOWN_MS as O,UPSTREAM_RECONNECT_ENABLED as k,UPSTREAM_RECONNECT_ENABLED_FOR_STDIO as A,config as j,deriveAccessControlUrl as M,deriveLogIngestUrl as N}from"./env-Be4mEx1x.js";export{j as config};
1
+ import{ACCESS_CONTROL_HEADERS as e,ACCESS_CONTROL_TIMEOUT_MS as t,ACCESS_CONTROL_URL as n,APP_VERSION as r,CLIENT_APP_NAME as i,DEBUG_MODE as a,LOG_DIR as o,LOG_INGEST_ENABLED as s,LOG_INGEST_TIMEOUT_MS as c,LOG_INGEST_URL as l,MIRROR_URL as u,OAUTH_DIR as d,OAUTH_PROVIDERS_TIMEOUT_MS as f,OAUTH_PROVIDERS_URL as p,PROXY_COMMAND as m,SCANNER_API_KEY as h,SCANNER_FAIL_OPEN as g,SCANNER_HEADERS as _,SCANNER_TIMEOUT_MS as v,SCANNER_URL as y,SESSION_ID as b,TOOL_CALL_MAX_TOTAL_TIMEOUT_MS as x,TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS as S,TOOL_CALL_TIMEOUT_MS as C,UPSTREAM_CONNECT_INITIAL_DELAY_MS as w,UPSTREAM_CONNECT_MAX_DELAY_MS as T,UPSTREAM_CONNECT_MAX_ELAPSED_MS as E,UPSTREAM_CONNECT_MAX_RETRIES as D,UPSTREAM_RECONNECT_COOLDOWN_MS as O,UPSTREAM_RECONNECT_ENABLED as k,UPSTREAM_RECONNECT_ENABLED_FOR_STDIO as A,config as j,deriveAccessControlUrl as M,deriveLogIngestUrl as N}from"./env-DRmaf9c0.js";export{j as config};
@@ -1,2 +1,2 @@
1
- import{randomUUID as e}from"crypto";import t from"env-var";import{homedir as n}from"node:os";import{join as r}from"node:path";import"dotenv/config";const i={APP_VERSION:`2.1.2`},a=t.get,o=i.APP_VERSION,s=e=>{let t={};if(e){let n=e.split(`,`);for(let e of n){let[n,...r]=e.split(`:`);n&&r.length>0&&(t[n.trim()]=r.join(`:`).trim())}}return t},c=e=>{try{let t=new URL(e),n=t.pathname.split(`/`).filter(Boolean)[0]===`ingest`?`/ingest`:``;return`${t.protocol}//${t.host}${n}/endpoint-logs`}catch{return null}},l=/\/guard\/evaluate\/v1(\/?)$/,u=e=>{try{let t=new URL(e),n=t.pathname.replace(l,`/access-control/authorize$1`);return n===t.pathname?(console.warn(`[mcp-gateway] Warning: SCANNER_URL does not contain expected path "/guard/evaluate/v1". Access control URL derivation skipped. Current path: "${t.pathname}". Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`),null):(t.pathname=n,t.toString())}catch(e){return console.warn(`[mcp-gateway] Warning: Failed to parse SCANNER_URL as valid URL: ${e instanceof Error?e.message:String(e)}. Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`),null}},d=e(),f=a(`MCP_GATEWAY_DEBUG`).default(`false`).asBool(),p=a(`MCP_GATEWAY_SCANNER_URL`).default(``).asString()||null,m=a(`MCP_GATEWAY_SCANNER_API_KEY`).default(``).asString()||void 0,h=a(`MCP_GATEWAY_MIRROR_URL`).default(``).asString()||null,g=(()=>{let e=a(`MCP_GATEWAY_SCANNER_HEADERS`).required(!1).asString();return e?s(e):{}})(),_=a(`MCP_GATEWAY_SCANNER_TIMEOUT_MS`).default(`20000`).asIntPositive(),v=a(`MCP_GATEWAY_TOOL_TIMEOUT_MS`).default(`60000`).asIntPositive(),y=a(`MCP_GATEWAY_TOOL_MAX_TOTAL_TIMEOUT_MS`).default(`0`).asInt(),b=a(`MCP_GATEWAY_TOOL_RESET_TIMEOUT_ON_PROGRESS`).default(`true`).asBool(),x=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_RETRIES`).default(`3`).asInt(),S=a(`MCP_GATEWAY_UPSTREAM_CONNECT_INITIAL_DELAY_MS`).default(`500`).asIntPositive(),C=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_DELAY_MS`).default(`4000`).asIntPositive(),w=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_ELAPSED_MS`).default(`10000`).asInt(),T=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED`).default(`true`).asBool(),E=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED_FOR_STDIO`).default(`false`).asBool(),D=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_COOLDOWN_MS`).default(`1000`).asIntPositive(),O=a(`MCP_GATEWAY_SCANNER_FAIL_OPEN`).default(`true`).asBool(),k=a(`MCP_GATEWAY_COMMAND`).default(`mcp-gateway`).asString(),A=a(`CLIENT_APP_NAME`).default(``).asString(),j=a(`MCP_GATEWAY_LOG_DIR`).default(r(n(),`.onyx`,`mcp-gateway`,`logs`)).asString(),M=a(`MCP_GATEWAY_OAUTH_DIR`).default(r(n(),`.onyx`,`mcp-gateway`,`oauth`)).asString(),N=(()=>a(`MCP_GATEWAY_ACCESS_CONTROL_URL`).default(``).asString()||(p?u(p):null))(),P=(()=>{let e=a(`MCP_GATEWAY_ACCESS_CONTROL_HEADERS`).required(!1).asString();return e?s(e):{}})(),F=a(`MCP_GATEWAY_ACCESS_CONTROL_TIMEOUT_MS`).default(`3000`).asIntPositive(),I=a(`MCP_GATEWAY_OAUTH_PROVIDERS_URL`).default(``).asString()||null,L=a(`MCP_GATEWAY_OAUTH_PROVIDERS_TIMEOUT_MS`).default(`5000`).asIntPositive(),R=a(`MCP_GATEWAY_LOG_INGEST_ENABLED`).default(`true`).asBool(),z=a(`MCP_GATEWAY_LOG_INGEST_TIMEOUT_MS`).default(`5000`).asIntPositive(),B=(()=>a(`MCP_GATEWAY_LOG_INGEST_URL`).default(``).asString()||(h?c(h):p?c(p):null))(),V={accessControl:{enabled:!!(N&&m),headers:P,timeoutMs:F,url:N},appVersion:o,clientAppName:A,debug:f,logDir:j,logIngest:{apiKey:m,enabled:R&&!!(B&&m),timeoutMs:z,url:B},oauthDir:M,oauthProviders:{apiKey:m,enabled:!!(I&&m),timeoutMs:L,url:I},proxyCommand:k,scanner:{apiKey:m,enabled:!!p,failOpen:O,headers:g,timeoutMs:_,url:p},toolCall:{maxTotalTimeoutMs:y,resetTimeoutOnProgress:b,timeoutMs:v},upstream:{connect:{initialDelayMs:S,maxDelayMs:C,maxElapsedMs:w,maxRetries:x},reconnect:{cooldownMs:D,enabled:T,enabledForStdio:E}}};export{P as ACCESS_CONTROL_HEADERS,F as ACCESS_CONTROL_TIMEOUT_MS,N as ACCESS_CONTROL_URL,o as APP_VERSION,A as CLIENT_APP_NAME,f as DEBUG_MODE,j as LOG_DIR,R as LOG_INGEST_ENABLED,z as LOG_INGEST_TIMEOUT_MS,B as LOG_INGEST_URL,h as MIRROR_URL,M as OAUTH_DIR,L as OAUTH_PROVIDERS_TIMEOUT_MS,I as OAUTH_PROVIDERS_URL,k as PROXY_COMMAND,m as SCANNER_API_KEY,O as SCANNER_FAIL_OPEN,g as SCANNER_HEADERS,_ as SCANNER_TIMEOUT_MS,p as SCANNER_URL,d as SESSION_ID,y as TOOL_CALL_MAX_TOTAL_TIMEOUT_MS,b as TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS,v as TOOL_CALL_TIMEOUT_MS,S as UPSTREAM_CONNECT_INITIAL_DELAY_MS,C as UPSTREAM_CONNECT_MAX_DELAY_MS,w as UPSTREAM_CONNECT_MAX_ELAPSED_MS,x as UPSTREAM_CONNECT_MAX_RETRIES,D as UPSTREAM_RECONNECT_COOLDOWN_MS,T as UPSTREAM_RECONNECT_ENABLED,E as UPSTREAM_RECONNECT_ENABLED_FOR_STDIO,V as config,u as deriveAccessControlUrl,c as deriveLogIngestUrl};
2
- //# sourceMappingURL=env-Be4mEx1x.js.map
1
+ import{randomUUID as e}from"crypto";import t from"env-var";import{homedir as n}from"node:os";import{join as r}from"node:path";import"dotenv/config";const i={APP_VERSION:`2.1.3`},a=t.get,o=i.APP_VERSION,s=e=>{let t={};if(e){let n=e.split(`,`);for(let e of n){let[n,...r]=e.split(`:`);n&&r.length>0&&(t[n.trim()]=r.join(`:`).trim())}}return t},c=e=>{try{let t=new URL(e),n=t.pathname.split(`/`).filter(Boolean)[0]===`ingest`?`/ingest`:``;return`${t.protocol}//${t.host}${n}/endpoint-logs`}catch{return null}},l=/\/guard\/evaluate\/v1(\/?)$/,u=e=>{try{let t=new URL(e),n=t.pathname.replace(l,`/access-control/authorize$1`);return n===t.pathname?(console.warn(`[mcp-gateway] Warning: SCANNER_URL does not contain expected path "/guard/evaluate/v1". Access control URL derivation skipped. Current path: "${t.pathname}". Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`),null):(t.pathname=n,t.toString())}catch(e){return console.warn(`[mcp-gateway] Warning: Failed to parse SCANNER_URL as valid URL: ${e instanceof Error?e.message:String(e)}. Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`),null}},d=e(),f=a(`MCP_GATEWAY_DEBUG`).default(`false`).asBool(),p=a(`MCP_GATEWAY_SCANNER_URL`).default(``).asString()||null,m=a(`MCP_GATEWAY_SCANNER_API_KEY`).default(``).asString()||void 0,h=a(`MCP_GATEWAY_MIRROR_URL`).default(``).asString()||null,g=(()=>{let e=a(`MCP_GATEWAY_SCANNER_HEADERS`).required(!1).asString();return e?s(e):{}})(),_=a(`MCP_GATEWAY_SCANNER_TIMEOUT_MS`).default(`20000`).asIntPositive(),v=a(`MCP_GATEWAY_TOOL_TIMEOUT_MS`).default(`60000`).asIntPositive(),y=a(`MCP_GATEWAY_TOOL_MAX_TOTAL_TIMEOUT_MS`).default(`0`).asInt(),b=a(`MCP_GATEWAY_TOOL_RESET_TIMEOUT_ON_PROGRESS`).default(`true`).asBool(),x=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_RETRIES`).default(`3`).asInt(),S=a(`MCP_GATEWAY_UPSTREAM_CONNECT_INITIAL_DELAY_MS`).default(`500`).asIntPositive(),C=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_DELAY_MS`).default(`4000`).asIntPositive(),w=a(`MCP_GATEWAY_UPSTREAM_CONNECT_MAX_ELAPSED_MS`).default(`10000`).asInt(),T=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED`).default(`true`).asBool(),E=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED_FOR_STDIO`).default(`false`).asBool(),D=a(`MCP_GATEWAY_UPSTREAM_RECONNECT_COOLDOWN_MS`).default(`1000`).asIntPositive(),O=a(`MCP_GATEWAY_SCANNER_FAIL_OPEN`).default(`true`).asBool(),k=a(`MCP_GATEWAY_COMMAND`).default(`mcp-gateway`).asString(),A=a(`CLIENT_APP_NAME`).default(``).asString(),j=a(`MCP_GATEWAY_LOG_DIR`).default(r(n(),`.onyx`,`mcp-gateway`,`logs`)).asString(),M=a(`MCP_GATEWAY_OAUTH_DIR`).default(r(n(),`.onyx`,`mcp-gateway`,`oauth`)).asString(),N=(()=>a(`MCP_GATEWAY_ACCESS_CONTROL_URL`).default(``).asString()||(p?u(p):null))(),P=(()=>{let e=a(`MCP_GATEWAY_ACCESS_CONTROL_HEADERS`).required(!1).asString();return e?s(e):{}})(),F=a(`MCP_GATEWAY_ACCESS_CONTROL_TIMEOUT_MS`).default(`3000`).asIntPositive(),I=a(`MCP_GATEWAY_OAUTH_PROVIDERS_URL`).default(``).asString()||null,L=a(`MCP_GATEWAY_OAUTH_PROVIDERS_TIMEOUT_MS`).default(`5000`).asIntPositive(),R=a(`MCP_GATEWAY_LOG_INGEST_ENABLED`).default(`true`).asBool(),z=a(`MCP_GATEWAY_LOG_INGEST_TIMEOUT_MS`).default(`5000`).asIntPositive(),B=(()=>a(`MCP_GATEWAY_LOG_INGEST_URL`).default(``).asString()||(h?c(h):p?c(p):null))(),V={accessControl:{enabled:!!(N&&m),headers:P,timeoutMs:F,url:N},appVersion:o,clientAppName:A,debug:f,logDir:j,logIngest:{apiKey:m,enabled:R&&!!(B&&m),timeoutMs:z,url:B},oauthDir:M,oauthProviders:{apiKey:m,enabled:!!(I&&m),timeoutMs:L,url:I},proxyCommand:k,scanner:{apiKey:m,enabled:!!p,failOpen:O,headers:g,timeoutMs:_,url:p},toolCall:{maxTotalTimeoutMs:y,resetTimeoutOnProgress:b,timeoutMs:v},upstream:{connect:{initialDelayMs:S,maxDelayMs:C,maxElapsedMs:w,maxRetries:x},reconnect:{cooldownMs:D,enabled:T,enabledForStdio:E}}};export{P as ACCESS_CONTROL_HEADERS,F as ACCESS_CONTROL_TIMEOUT_MS,N as ACCESS_CONTROL_URL,o as APP_VERSION,A as CLIENT_APP_NAME,f as DEBUG_MODE,j as LOG_DIR,R as LOG_INGEST_ENABLED,z as LOG_INGEST_TIMEOUT_MS,B as LOG_INGEST_URL,h as MIRROR_URL,M as OAUTH_DIR,L as OAUTH_PROVIDERS_TIMEOUT_MS,I as OAUTH_PROVIDERS_URL,k as PROXY_COMMAND,m as SCANNER_API_KEY,O as SCANNER_FAIL_OPEN,g as SCANNER_HEADERS,_ as SCANNER_TIMEOUT_MS,p as SCANNER_URL,d as SESSION_ID,y as TOOL_CALL_MAX_TOTAL_TIMEOUT_MS,b as TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS,v as TOOL_CALL_TIMEOUT_MS,S as UPSTREAM_CONNECT_INITIAL_DELAY_MS,C as UPSTREAM_CONNECT_MAX_DELAY_MS,w as UPSTREAM_CONNECT_MAX_ELAPSED_MS,x as UPSTREAM_CONNECT_MAX_RETRIES,D as UPSTREAM_RECONNECT_COOLDOWN_MS,T as UPSTREAM_RECONNECT_ENABLED,E as UPSTREAM_RECONNECT_ENABLED_FOR_STDIO,V as config,u as deriveAccessControlUrl,c as deriveLogIngestUrl};
2
+ //# sourceMappingURL=env-DRmaf9c0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"env-Be4mEx1x.js","names":["BUILD_TIME_CONFIG: BuildTimeConfig","headers: Record<string, string>"],"sources":["../src/config/config.generated.ts","../src/config/env.ts"],"sourcesContent":["// THIS FILE IS AUTO-GENERATED - DO NOT EDIT MANUALLY\n// Generated at build time from package.json\n\nimport type { BuildTimeConfig } from \"./config.js\";\n\nexport const BUILD_TIME_CONFIG: BuildTimeConfig = {\n \"APP_VERSION\": \"2.1.2\"\n};\n","import { randomUUID } from \"crypto\";\nimport envVar from \"env-var\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport \"dotenv/config\";\n\nconst env = envVar.get;\n\nimport { BUILD_TIME_CONFIG } from \"./config.generated.js\";\n\nexport const APP_VERSION = BUILD_TIME_CONFIG.APP_VERSION;\n\n// Helper function to parse headers from environment variable\nconst parseHeaders = (headerString: string): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (headerString) {\n const headerPairs = headerString.split(\",\");\n for (const pair of headerPairs) {\n const [key, ...valueParts] = pair.split(\":\");\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join(\":\").trim();\n }\n }\n }\n return headers;\n};\n\n// Helper function to derive log ingest URL from scanner URL\n// Extracts scheme and host, appends /endpoint-logs path\n// Preserves /ingest prefix if present (needed for local setups)\n// Exported for testing\nexport const deriveLogIngestUrl = (scannerUrl: string): null | string => {\n try {\n const url = new URL(scannerUrl);\n // Check if first path segment is /ingest - preserve it for local setups\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n const basePath = pathParts[0] === \"ingest\" ? \"/ingest\" : \"\";\n return `${url.protocol}//${url.host}${basePath}/endpoint-logs`;\n } catch {\n return null;\n }\n};\n\n// Helper function to derive access control URL from scanner URL.\n//\n// SCANNER_URL and ACCESS_CONTROL_URL share the same host in production\n// (https://ai-guard.<tenant>/...), so when ACCESS_CONTROL_URL isn't set\n// explicitly we can swap the scanner path suffix for /access-control/authorize.\n//\n// Uses an anchored regex so a SCANNER_URL whose path is /guard/evaluate/v1-extra\n// or /guard/evaluate/v10 is treated as a non-match (returns null) rather than\n// producing a malformed URL.\n//\n// Note: this same-host assumption does NOT hold for the OAuth providers\n// endpoint, which lives on a different host (api.<tenant>) than the scanner.\n// MCP_GATEWAY_OAUTH_PROVIDERS_URL must be set explicitly — it is wired\n// through CI distribute-scanner.yaml and the install-script ONYX_ENV_VARS\n// pipeline, so it always arrives as a concrete URL in production.\n//\n// Exported for testing.\nconst accessControlPathRegex = /\\/guard\\/evaluate\\/v1(\\/?)$/;\n\nexport const deriveAccessControlUrl = (scannerUrl: string): null | string => {\n try {\n const url = new URL(scannerUrl);\n const expectedPath = \"/guard/evaluate/v1\";\n const replaced = url.pathname.replace(\n accessControlPathRegex,\n \"/access-control/authorize$1\"\n );\n\n if (replaced === url.pathname) {\n // Warn about non-standard format (can't use logger due to circular dependency)\n console.warn(\n `[mcp-gateway] Warning: SCANNER_URL does not contain expected path \"${expectedPath}\". ` +\n `Access control URL derivation skipped. Current path: \"${url.pathname}\". ` +\n `Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`\n );\n return null;\n }\n\n url.pathname = replaced;\n return url.toString();\n } catch (error) {\n // Invalid URL format\n console.warn(\n `[mcp-gateway] Warning: Failed to parse SCANNER_URL as valid URL: ${error instanceof Error ? error.message : String(error)}. ` +\n `Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`\n );\n return null;\n }\n};\n\nexport const SESSION_ID = randomUUID();\n\nexport const DEBUG_MODE = env(\"MCP_GATEWAY_DEBUG\").default(\"false\").asBool();\n\nexport const SCANNER_URL = env(\"MCP_GATEWAY_SCANNER_URL\").default(\"\").asString() || null;\n\nexport const SCANNER_API_KEY = env(\"MCP_GATEWAY_SCANNER_API_KEY\").default(\"\").asString() || undefined;\n\nexport const MIRROR_URL = env(\"MCP_GATEWAY_MIRROR_URL\").default(\"\").asString() || null;\n\nexport const SCANNER_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_SCANNER_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const SCANNER_TIMEOUT_MS = env(\"MCP_GATEWAY_SCANNER_TIMEOUT_MS\").default(\"20000\").asIntPositive();\n\n// Forwarded tool-call timeout knobs.\n//\n// The MCP SDK defaults every forwarded request to a 60s timeout\n// (DEFAULT_REQUEST_TIMEOUT_MSEC) with no progress-based reset, and the gateway\n// previously forwarded no RequestOptions at all. That capped long-running\n// upstream tools (e.g. slow DB queries) at 60s regardless of the client's own\n// timeout. These knobs raise the per-request ceiling and opt into resetting it\n// on upstream progress. See src/proxyServer.ts.\nexport const TOOL_CALL_TIMEOUT_MS = env(\"MCP_GATEWAY_TOOL_TIMEOUT_MS\").default(\"60000\").asIntPositive();\n\n// Absolute ceiling across progress resets. 0 (default) disables the cap, which\n// matches the SDK semantics of an undefined maxTotalTimeout.\nexport const TOOL_CALL_MAX_TOTAL_TIMEOUT_MS = env(\"MCP_GATEWAY_TOOL_MAX_TOTAL_TIMEOUT_MS\").default(\"0\").asInt();\n\n// When true (default), each upstream progress notification resets the\n// per-request timeout, and progress is forwarded on to the client. Only has an\n// effect for upstream servers that actually emit progress notifications.\nexport const TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS = env(\"MCP_GATEWAY_TOOL_RESET_TIMEOUT_ON_PROGRESS\").default(\"true\").asBool();\n\n// Upstream connect-time resilience knobs.\n//\n// The gateway connects to the upstream MCP server once at startup and treats a\n// failure as fatal (\"MCP server failed to start\"). Upstream reachability can\n// flap (DNS/VPN blips, brief outages) and self-recover within seconds, so a\n// bounded retry-with-backoff at connect time turns most transient failures into\n// a successful start instead of a dead session. The whole budget must stay\n// under the MCP client's own server-startup timeout, hence the wall-clock cap.\n// See src/lib/connectWithRetry.ts.\nexport const UPSTREAM_CONNECT_MAX_RETRIES = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_RETRIES\").default(\"3\").asInt();\n\nexport const UPSTREAM_CONNECT_INITIAL_DELAY_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_INITIAL_DELAY_MS\").default(\"500\").asIntPositive();\n\nexport const UPSTREAM_CONNECT_MAX_DELAY_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_DELAY_MS\").default(\"4000\").asIntPositive();\n\n// Hard wall-clock cap across all connect attempts. 0 disables the cap.\nexport const UPSTREAM_CONNECT_MAX_ELAPSED_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_ELAPSED_MS\").default(\"10000\").asInt();\n\n// Mid-session reconnect knobs.\n//\n// Once connected, the upstream can still drop mid-session (the same reachability\n// flap, or a terminated/expired session). Rather than leaving the session dead\n// until the user restarts the client, the gateway rebuilds the upstream\n// connection on a recoverable failure and retries the call. Scoped to REMOTE\n// upstreams by default: a stdio \"reconnect\" respawns the child and loses its\n// in-memory state, so it's opt-in. Reconnect is driven by traffic (one attempt\n// per failing call, deduped) with a cooldown to collapse bursts — no background\n// loop. See src/lib/reconnectingClient.ts.\nexport const UPSTREAM_RECONNECT_ENABLED = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED\").default(\"true\").asBool();\n\nexport const UPSTREAM_RECONNECT_ENABLED_FOR_STDIO = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED_FOR_STDIO\").default(\"false\").asBool();\n\n// Minimum gap between reconnect attempts, so a burst of concurrent failed calls\n// triggers at most one reconnect per window.\nexport const UPSTREAM_RECONNECT_COOLDOWN_MS = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_COOLDOWN_MS\").default(\"1000\").asIntPositive();\n\nexport const SCANNER_FAIL_OPEN = env(\"MCP_GATEWAY_SCANNER_FAIL_OPEN\").default(\"true\").asBool();\n\nexport const PROXY_COMMAND = env(\"MCP_GATEWAY_COMMAND\").default(\"mcp-gateway\").asString();\n\nexport const CLIENT_APP_NAME = env(\"CLIENT_APP_NAME\").default(\"\").asString();\n\nexport const LOG_DIR = env(\"MCP_GATEWAY_LOG_DIR\")\n .default(join(homedir(), \".onyx\", \"mcp-gateway\", \"logs\"))\n .asString();\n\nexport const OAUTH_DIR = env(\"MCP_GATEWAY_OAUTH_DIR\")\n .default(join(homedir(), \".onyx\", \"mcp-gateway\", \"oauth\"))\n .asString();\n\nexport const ACCESS_CONTROL_URL = (() => {\n const explicitUrl = env(\"MCP_GATEWAY_ACCESS_CONTROL_URL\").default(\"\").asString();\n if (explicitUrl) {\n return explicitUrl;\n }\n // If not explicitly set, derive from scanner URL\n if (SCANNER_URL) {\n return deriveAccessControlUrl(SCANNER_URL);\n }\n return null;\n})();\n\nexport const ACCESS_CONTROL_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_ACCESS_CONTROL_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const ACCESS_CONTROL_TIMEOUT_MS = env(\"MCP_GATEWAY_ACCESS_CONTROL_TIMEOUT_MS\").default(\"3000\").asIntPositive();\n\n// OAuth providers configuration (fetched from web extension service at startup).\n//\n// Set explicitly per-tenant via MCP_GATEWAY_OAUTH_PROVIDERS_URL or the\n// --oauth-providers-url CLI flag. Unlike SCANNER_URL/ACCESS_CONTROL_URL, the\n// OAuth providers endpoint lives on a different host (api.<tenant>) than the\n// scanner (ai-guard.<tenant>) — so we cannot derive it from SCANNER_URL and\n// must rely on the install pipeline to inject the concrete URL.\nexport const OAUTH_PROVIDERS_URL =\n env(\"MCP_GATEWAY_OAUTH_PROVIDERS_URL\").default(\"\").asString() || null;\n\nexport const OAUTH_PROVIDERS_TIMEOUT_MS = env(\"MCP_GATEWAY_OAUTH_PROVIDERS_TIMEOUT_MS\").default(\"5000\").asIntPositive();\n\n// Log ingest configuration (for Groundcover logging)\nexport const LOG_INGEST_ENABLED = env(\"MCP_GATEWAY_LOG_INGEST_ENABLED\").default(\"true\").asBool();\n\nexport const LOG_INGEST_TIMEOUT_MS = env(\"MCP_GATEWAY_LOG_INGEST_TIMEOUT_MS\").default(\"5000\").asIntPositive();\n\nexport const LOG_INGEST_URL = (() => {\n const explicitUrl = env(\"MCP_GATEWAY_LOG_INGEST_URL\").default(\"\").asString();\n if (explicitUrl) {\n return explicitUrl;\n }\n // Derive from mirror URL (on ingest.* host) since SCANNER_URL points to\n // ai-guard.* which doesn't have an /endpoint-logs route\n if (MIRROR_URL) {\n return deriveLogIngestUrl(MIRROR_URL);\n }\n if (SCANNER_URL) {\n return deriveLogIngestUrl(SCANNER_URL);\n }\n return null;\n})();\n\nexport const config = {\n accessControl: {\n enabled: Boolean(ACCESS_CONTROL_URL && SCANNER_API_KEY),\n headers: ACCESS_CONTROL_HEADERS,\n timeoutMs: ACCESS_CONTROL_TIMEOUT_MS,\n url: ACCESS_CONTROL_URL,\n },\n appVersion: APP_VERSION,\n clientAppName: CLIENT_APP_NAME,\n debug: DEBUG_MODE,\n logDir: LOG_DIR,\n logIngest: {\n apiKey: SCANNER_API_KEY,\n enabled: LOG_INGEST_ENABLED && Boolean(LOG_INGEST_URL && SCANNER_API_KEY),\n timeoutMs: LOG_INGEST_TIMEOUT_MS,\n url: LOG_INGEST_URL,\n },\n oauthDir: OAUTH_DIR,\n oauthProviders: {\n apiKey: SCANNER_API_KEY,\n enabled: Boolean(OAUTH_PROVIDERS_URL && SCANNER_API_KEY),\n timeoutMs: OAUTH_PROVIDERS_TIMEOUT_MS,\n url: OAUTH_PROVIDERS_URL,\n },\n proxyCommand: PROXY_COMMAND,\n scanner: {\n apiKey: SCANNER_API_KEY,\n enabled: Boolean(SCANNER_URL),\n failOpen: SCANNER_FAIL_OPEN,\n headers: SCANNER_HEADERS,\n timeoutMs: SCANNER_TIMEOUT_MS,\n url: SCANNER_URL,\n },\n toolCall: {\n maxTotalTimeoutMs: TOOL_CALL_MAX_TOTAL_TIMEOUT_MS,\n resetTimeoutOnProgress: TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS,\n timeoutMs: TOOL_CALL_TIMEOUT_MS,\n },\n upstream: {\n connect: {\n initialDelayMs: UPSTREAM_CONNECT_INITIAL_DELAY_MS,\n maxDelayMs: UPSTREAM_CONNECT_MAX_DELAY_MS,\n maxElapsedMs: UPSTREAM_CONNECT_MAX_ELAPSED_MS,\n maxRetries: UPSTREAM_CONNECT_MAX_RETRIES,\n },\n reconnect: {\n cooldownMs: UPSTREAM_RECONNECT_COOLDOWN_MS,\n enabled: UPSTREAM_RECONNECT_ENABLED,\n enabledForStdio: UPSTREAM_RECONNECT_ENABLED_FOR_STDIO,\n },\n },\n} as const;\n\n// Note: Don't use the logger here to avoid circular dependency issues\n// The logger hasn't been initialized yet when this config file is imported\n// Configuration is logged to file by the logger once initialized\n"],"mappings":"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"}
1
+ {"version":3,"file":"env-DRmaf9c0.js","names":["BUILD_TIME_CONFIG: BuildTimeConfig","headers: Record<string, string>"],"sources":["../src/config/config.generated.ts","../src/config/env.ts"],"sourcesContent":["// THIS FILE IS AUTO-GENERATED - DO NOT EDIT MANUALLY\n// Generated at build time from package.json\n\nimport type { BuildTimeConfig } from \"./config.js\";\n\nexport const BUILD_TIME_CONFIG: BuildTimeConfig = {\n \"APP_VERSION\": \"2.1.3\"\n};\n","import { randomUUID } from \"crypto\";\nimport envVar from \"env-var\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport \"dotenv/config\";\n\nconst env = envVar.get;\n\nimport { BUILD_TIME_CONFIG } from \"./config.generated.js\";\n\nexport const APP_VERSION = BUILD_TIME_CONFIG.APP_VERSION;\n\n// Helper function to parse headers from environment variable\nconst parseHeaders = (headerString: string): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (headerString) {\n const headerPairs = headerString.split(\",\");\n for (const pair of headerPairs) {\n const [key, ...valueParts] = pair.split(\":\");\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join(\":\").trim();\n }\n }\n }\n return headers;\n};\n\n// Helper function to derive log ingest URL from scanner URL\n// Extracts scheme and host, appends /endpoint-logs path\n// Preserves /ingest prefix if present (needed for local setups)\n// Exported for testing\nexport const deriveLogIngestUrl = (scannerUrl: string): null | string => {\n try {\n const url = new URL(scannerUrl);\n // Check if first path segment is /ingest - preserve it for local setups\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n const basePath = pathParts[0] === \"ingest\" ? \"/ingest\" : \"\";\n return `${url.protocol}//${url.host}${basePath}/endpoint-logs`;\n } catch {\n return null;\n }\n};\n\n// Helper function to derive access control URL from scanner URL.\n//\n// SCANNER_URL and ACCESS_CONTROL_URL share the same host in production\n// (https://ai-guard.<tenant>/...), so when ACCESS_CONTROL_URL isn't set\n// explicitly we can swap the scanner path suffix for /access-control/authorize.\n//\n// Uses an anchored regex so a SCANNER_URL whose path is /guard/evaluate/v1-extra\n// or /guard/evaluate/v10 is treated as a non-match (returns null) rather than\n// producing a malformed URL.\n//\n// Note: this same-host assumption does NOT hold for the OAuth providers\n// endpoint, which lives on a different host (api.<tenant>) than the scanner.\n// MCP_GATEWAY_OAUTH_PROVIDERS_URL must be set explicitly — it is wired\n// through CI distribute-scanner.yaml and the install-script ONYX_ENV_VARS\n// pipeline, so it always arrives as a concrete URL in production.\n//\n// Exported for testing.\nconst accessControlPathRegex = /\\/guard\\/evaluate\\/v1(\\/?)$/;\n\nexport const deriveAccessControlUrl = (scannerUrl: string): null | string => {\n try {\n const url = new URL(scannerUrl);\n const expectedPath = \"/guard/evaluate/v1\";\n const replaced = url.pathname.replace(\n accessControlPathRegex,\n \"/access-control/authorize$1\"\n );\n\n if (replaced === url.pathname) {\n // Warn about non-standard format (can't use logger due to circular dependency)\n console.warn(\n `[mcp-gateway] Warning: SCANNER_URL does not contain expected path \"${expectedPath}\". ` +\n `Access control URL derivation skipped. Current path: \"${url.pathname}\". ` +\n `Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`\n );\n return null;\n }\n\n url.pathname = replaced;\n return url.toString();\n } catch (error) {\n // Invalid URL format\n console.warn(\n `[mcp-gateway] Warning: Failed to parse SCANNER_URL as valid URL: ${error instanceof Error ? error.message : String(error)}. ` +\n `Please set MCP_GATEWAY_ACCESS_CONTROL_URL explicitly.`\n );\n return null;\n }\n};\n\nexport const SESSION_ID = randomUUID();\n\nexport const DEBUG_MODE = env(\"MCP_GATEWAY_DEBUG\").default(\"false\").asBool();\n\nexport const SCANNER_URL = env(\"MCP_GATEWAY_SCANNER_URL\").default(\"\").asString() || null;\n\nexport const SCANNER_API_KEY = env(\"MCP_GATEWAY_SCANNER_API_KEY\").default(\"\").asString() || undefined;\n\nexport const MIRROR_URL = env(\"MCP_GATEWAY_MIRROR_URL\").default(\"\").asString() || null;\n\nexport const SCANNER_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_SCANNER_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const SCANNER_TIMEOUT_MS = env(\"MCP_GATEWAY_SCANNER_TIMEOUT_MS\").default(\"20000\").asIntPositive();\n\n// Forwarded tool-call timeout knobs.\n//\n// The MCP SDK defaults every forwarded request to a 60s timeout\n// (DEFAULT_REQUEST_TIMEOUT_MSEC) with no progress-based reset, and the gateway\n// previously forwarded no RequestOptions at all. That capped long-running\n// upstream tools (e.g. slow DB queries) at 60s regardless of the client's own\n// timeout. These knobs raise the per-request ceiling and opt into resetting it\n// on upstream progress. See src/proxyServer.ts.\nexport const TOOL_CALL_TIMEOUT_MS = env(\"MCP_GATEWAY_TOOL_TIMEOUT_MS\").default(\"60000\").asIntPositive();\n\n// Absolute ceiling across progress resets. 0 (default) disables the cap, which\n// matches the SDK semantics of an undefined maxTotalTimeout.\nexport const TOOL_CALL_MAX_TOTAL_TIMEOUT_MS = env(\"MCP_GATEWAY_TOOL_MAX_TOTAL_TIMEOUT_MS\").default(\"0\").asInt();\n\n// When true (default), each upstream progress notification resets the\n// per-request timeout, and progress is forwarded on to the client. Only has an\n// effect for upstream servers that actually emit progress notifications.\nexport const TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS = env(\"MCP_GATEWAY_TOOL_RESET_TIMEOUT_ON_PROGRESS\").default(\"true\").asBool();\n\n// Upstream connect-time resilience knobs.\n//\n// The gateway connects to the upstream MCP server once at startup and treats a\n// failure as fatal (\"MCP server failed to start\"). Upstream reachability can\n// flap (DNS/VPN blips, brief outages) and self-recover within seconds, so a\n// bounded retry-with-backoff at connect time turns most transient failures into\n// a successful start instead of a dead session. The whole budget must stay\n// under the MCP client's own server-startup timeout, hence the wall-clock cap.\n// See src/lib/connectWithRetry.ts.\nexport const UPSTREAM_CONNECT_MAX_RETRIES = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_RETRIES\").default(\"3\").asInt();\n\nexport const UPSTREAM_CONNECT_INITIAL_DELAY_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_INITIAL_DELAY_MS\").default(\"500\").asIntPositive();\n\nexport const UPSTREAM_CONNECT_MAX_DELAY_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_DELAY_MS\").default(\"4000\").asIntPositive();\n\n// Hard wall-clock cap across all connect attempts. 0 disables the cap.\nexport const UPSTREAM_CONNECT_MAX_ELAPSED_MS = env(\"MCP_GATEWAY_UPSTREAM_CONNECT_MAX_ELAPSED_MS\").default(\"10000\").asInt();\n\n// Mid-session reconnect knobs.\n//\n// Once connected, the upstream can still drop mid-session (the same reachability\n// flap, or a terminated/expired session). Rather than leaving the session dead\n// until the user restarts the client, the gateway rebuilds the upstream\n// connection on a recoverable failure and retries the call. Scoped to REMOTE\n// upstreams by default: a stdio \"reconnect\" respawns the child and loses its\n// in-memory state, so it's opt-in. Reconnect is driven by traffic (one attempt\n// per failing call, deduped) with a cooldown to collapse bursts — no background\n// loop. See src/lib/reconnectingClient.ts.\nexport const UPSTREAM_RECONNECT_ENABLED = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED\").default(\"true\").asBool();\n\nexport const UPSTREAM_RECONNECT_ENABLED_FOR_STDIO = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_ENABLED_FOR_STDIO\").default(\"false\").asBool();\n\n// Minimum gap between reconnect attempts, so a burst of concurrent failed calls\n// triggers at most one reconnect per window.\nexport const UPSTREAM_RECONNECT_COOLDOWN_MS = env(\"MCP_GATEWAY_UPSTREAM_RECONNECT_COOLDOWN_MS\").default(\"1000\").asIntPositive();\n\nexport const SCANNER_FAIL_OPEN = env(\"MCP_GATEWAY_SCANNER_FAIL_OPEN\").default(\"true\").asBool();\n\nexport const PROXY_COMMAND = env(\"MCP_GATEWAY_COMMAND\").default(\"mcp-gateway\").asString();\n\nexport const CLIENT_APP_NAME = env(\"CLIENT_APP_NAME\").default(\"\").asString();\n\nexport const LOG_DIR = env(\"MCP_GATEWAY_LOG_DIR\")\n .default(join(homedir(), \".onyx\", \"mcp-gateway\", \"logs\"))\n .asString();\n\nexport const OAUTH_DIR = env(\"MCP_GATEWAY_OAUTH_DIR\")\n .default(join(homedir(), \".onyx\", \"mcp-gateway\", \"oauth\"))\n .asString();\n\nexport const ACCESS_CONTROL_URL = (() => {\n const explicitUrl = env(\"MCP_GATEWAY_ACCESS_CONTROL_URL\").default(\"\").asString();\n if (explicitUrl) {\n return explicitUrl;\n }\n // If not explicitly set, derive from scanner URL\n if (SCANNER_URL) {\n return deriveAccessControlUrl(SCANNER_URL);\n }\n return null;\n})();\n\nexport const ACCESS_CONTROL_HEADERS = (() => {\n const runtimeHeaders = env(\"MCP_GATEWAY_ACCESS_CONTROL_HEADERS\").required(false).asString();\n if (runtimeHeaders) {\n return parseHeaders(runtimeHeaders);\n }\n return {};\n})();\n\nexport const ACCESS_CONTROL_TIMEOUT_MS = env(\"MCP_GATEWAY_ACCESS_CONTROL_TIMEOUT_MS\").default(\"3000\").asIntPositive();\n\n// OAuth providers configuration (fetched from web extension service at startup).\n//\n// Set explicitly per-tenant via MCP_GATEWAY_OAUTH_PROVIDERS_URL or the\n// --oauth-providers-url CLI flag. Unlike SCANNER_URL/ACCESS_CONTROL_URL, the\n// OAuth providers endpoint lives on a different host (api.<tenant>) than the\n// scanner (ai-guard.<tenant>) — so we cannot derive it from SCANNER_URL and\n// must rely on the install pipeline to inject the concrete URL.\nexport const OAUTH_PROVIDERS_URL =\n env(\"MCP_GATEWAY_OAUTH_PROVIDERS_URL\").default(\"\").asString() || null;\n\nexport const OAUTH_PROVIDERS_TIMEOUT_MS = env(\"MCP_GATEWAY_OAUTH_PROVIDERS_TIMEOUT_MS\").default(\"5000\").asIntPositive();\n\n// Log ingest configuration (for Groundcover logging)\nexport const LOG_INGEST_ENABLED = env(\"MCP_GATEWAY_LOG_INGEST_ENABLED\").default(\"true\").asBool();\n\nexport const LOG_INGEST_TIMEOUT_MS = env(\"MCP_GATEWAY_LOG_INGEST_TIMEOUT_MS\").default(\"5000\").asIntPositive();\n\nexport const LOG_INGEST_URL = (() => {\n const explicitUrl = env(\"MCP_GATEWAY_LOG_INGEST_URL\").default(\"\").asString();\n if (explicitUrl) {\n return explicitUrl;\n }\n // Derive from mirror URL (on ingest.* host) since SCANNER_URL points to\n // ai-guard.* which doesn't have an /endpoint-logs route\n if (MIRROR_URL) {\n return deriveLogIngestUrl(MIRROR_URL);\n }\n if (SCANNER_URL) {\n return deriveLogIngestUrl(SCANNER_URL);\n }\n return null;\n})();\n\nexport const config = {\n accessControl: {\n enabled: Boolean(ACCESS_CONTROL_URL && SCANNER_API_KEY),\n headers: ACCESS_CONTROL_HEADERS,\n timeoutMs: ACCESS_CONTROL_TIMEOUT_MS,\n url: ACCESS_CONTROL_URL,\n },\n appVersion: APP_VERSION,\n clientAppName: CLIENT_APP_NAME,\n debug: DEBUG_MODE,\n logDir: LOG_DIR,\n logIngest: {\n apiKey: SCANNER_API_KEY,\n enabled: LOG_INGEST_ENABLED && Boolean(LOG_INGEST_URL && SCANNER_API_KEY),\n timeoutMs: LOG_INGEST_TIMEOUT_MS,\n url: LOG_INGEST_URL,\n },\n oauthDir: OAUTH_DIR,\n oauthProviders: {\n apiKey: SCANNER_API_KEY,\n enabled: Boolean(OAUTH_PROVIDERS_URL && SCANNER_API_KEY),\n timeoutMs: OAUTH_PROVIDERS_TIMEOUT_MS,\n url: OAUTH_PROVIDERS_URL,\n },\n proxyCommand: PROXY_COMMAND,\n scanner: {\n apiKey: SCANNER_API_KEY,\n enabled: Boolean(SCANNER_URL),\n failOpen: SCANNER_FAIL_OPEN,\n headers: SCANNER_HEADERS,\n timeoutMs: SCANNER_TIMEOUT_MS,\n url: SCANNER_URL,\n },\n toolCall: {\n maxTotalTimeoutMs: TOOL_CALL_MAX_TOTAL_TIMEOUT_MS,\n resetTimeoutOnProgress: TOOL_CALL_RESET_TIMEOUT_ON_PROGRESS,\n timeoutMs: TOOL_CALL_TIMEOUT_MS,\n },\n upstream: {\n connect: {\n initialDelayMs: UPSTREAM_CONNECT_INITIAL_DELAY_MS,\n maxDelayMs: UPSTREAM_CONNECT_MAX_DELAY_MS,\n maxElapsedMs: UPSTREAM_CONNECT_MAX_ELAPSED_MS,\n maxRetries: UPSTREAM_CONNECT_MAX_RETRIES,\n },\n reconnect: {\n cooldownMs: UPSTREAM_RECONNECT_COOLDOWN_MS,\n enabled: UPSTREAM_RECONNECT_ENABLED,\n enabledForStdio: UPSTREAM_RECONNECT_ENABLED_FOR_STDIO,\n },\n },\n} as const;\n\n// Note: Don't use the logger here to avoid circular dependency issues\n// The logger hasn't been initialized yet when this config file is imported\n// Configuration is logged to file by the logger once initialized\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{Client as e,InMemoryEventStore as t,Server as n,StdioServerTransport as r,proxyServer as i,startHTTPServer as a}from"./stdio-C7WPd4gY.js";import{SSEClientTransport as o,StreamableHTTPClientTransport as s,normalizeUrl as c}from"./normalizeUrl-BrUSzVK4.js";import{config as l}from"./env-Be4mEx1x.js";import"./logger-DSLFCg6q.js";let u=function(e){return e.HTTPStream=`HTTPStream`,e.SSE=`SSE`,e}({});const d=async({initStdioServer:t,initStreamClient:a,serverType:d,transportOptions:f={},url:p})=>{let m=c(p),h;switch(d){case u.SSE:h=new o(new URL(m),f);break;default:h=new s(new URL(m),f)}let g=a?await a():new e({name:`mcp-gateway`,version:l.appVersion},{capabilities:{}});await g.connect(h);let _=g.getServerVersion(),v=g.getServerCapabilities(),y=t?await t():new n(_,{capabilities:v}),b=new r;return await y.connect(b),await i({authorizer:void 0,client:g,server:y,serverCapabilities:v}),y},f=(e,t)=>{let n=e.close.bind(e),r=e.onclose?.bind(e),i=e.onerror?.bind(e),a=e.onmessage?.bind(e),o=e.send.bind(e),s=e.start.bind(e);return e.close=async()=>(t({type:`close`}),n?.()),e.onclose=async()=>(t({type:`onclose`}),r?.()),e.onerror=async e=>(t({error:e,type:`onerror`}),i?.(e)),e.onmessage=async e=>(t({message:e,type:`onmessage`}),a?.(e)),e.send=async e=>(t({message:e,type:`send`}),o?.(e)),e.start=async()=>(t({type:`start`}),s?.()),e};export{t as InMemoryEventStore,u as ServerType,i as proxyServer,a as startHTTPServer,d as startStdioServer,f as tapTransport};
1
+ import{Client as e,InMemoryEventStore as t,Server as n,StdioServerTransport as r,proxyServer as i,startHTTPServer as a}from"./stdio-BcV6UBJk.js";import{SSEClientTransport as o,StreamableHTTPClientTransport as s,normalizeUrl as c}from"./normalizeUrl-BrUSzVK4.js";import{config as l}from"./env-DRmaf9c0.js";import"./logger-ztMIFOl1.js";let u=function(e){return e.HTTPStream=`HTTPStream`,e.SSE=`SSE`,e}({});const d=async({initStdioServer:t,initStreamClient:a,serverType:d,transportOptions:f={},url:p})=>{let m=c(p),h;switch(d){case u.SSE:h=new o(new URL(m),f);break;default:h=new s(new URL(m),f)}let g=a?await a():new e({name:`mcp-gateway`,version:l.appVersion},{capabilities:{}});await g.connect(h);let _=g.getServerVersion(),v=g.getServerCapabilities(),y=t?await t():new n(_,{capabilities:v}),b=new r;return await y.connect(b),await i({authorizer:void 0,client:g,server:y,serverCapabilities:v}),y},f=(e,t)=>{let n=e.close.bind(e),r=e.onclose?.bind(e),i=e.onerror?.bind(e),a=e.onmessage?.bind(e),o=e.send.bind(e),s=e.start.bind(e);return e.close=async()=>(t({type:`close`}),n?.()),e.onclose=async()=>(t({type:`onclose`}),r?.()),e.onerror=async e=>(t({error:e,type:`onerror`}),i?.(e)),e.onmessage=async e=>(t({message:e,type:`onmessage`}),a?.(e)),e.send=async e=>(t({message:e,type:`send`}),o?.(e)),e.start=async()=>(t({type:`start`}),s?.()),e};export{t as InMemoryEventStore,u as ServerType,i as proxyServer,a as startHTTPServer,d as startStdioServer,f as tapTransport};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- import{__commonJSMin as e,__require as t,__toESM as n}from"./chunk-CrDKVgUD.js";import{config as r}from"./env-Be4mEx1x.js";import{arch as i,hostname as a,platform as o}from"node:os";import{join as s,sep as c}from"node:path";import{AsyncLocalStorage as l}from"node:async_hooks";import{randomUUID as u}from"node:crypto";import{chownSync as d,existsSync as f,mkdirSync as p}from"node:fs";import m from"winston";import h from"winston-daily-rotate-file";import{chown as g}from"node:fs/promises";async function _(e){let t=b();if(!t)return;let n=y(e);if(!n){await g(e,t.uid,t.gid);return}for(let e of n)await g(e,t.uid,t.gid)}function v(e){let t=b();if(!t)return;let n=y(e);if(!n){d(e,t.uid,t.gid);return}for(let e of n)d(e,t.uid,t.gid)}function y(e){if(!e.startsWith(c))return;let t=e.split(c),n=t.indexOf(`.onyx`);if(n===-1)return;let r=[];for(let e=n;e<t.length;e++)r.push(t.slice(0,e+1).join(c));return r}function b(){if(typeof process.getuid!=`function`||process.getuid()!==0)return;let e=process.env.SUDO_UID,t=process.env.SUDO_GID;if(!e||!t)return;let n=parseInt(e,10),r=parseInt(t,10);if(!(isNaN(n)||isNaN(r)))return{gid:r,uid:n}}var x=e(((exports,n)=>{n.exports=t(`util`).deprecate})),ee=e(((exports,n)=>{n.exports=t(`stream`)})),te=e(((exports,t)=>{function n(e,t){var n=this,a=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return a||s?(t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(o,this,e)):process.nextTick(o,this,e)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?n._writableState?n._writableState.errorEmitted?process.nextTick(i,n):(n._writableState.errorEmitted=!0,process.nextTick(r,n,e)):process.nextTick(r,n,e):t?(process.nextTick(i,n),t(e)):process.nextTick(i,n)}),this)}function r(e,t){o(e,t),i(e)}function i(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit(`close`)}function a(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function o(e,t){e.emit(`error`,t)}function s(e,t){var n=e._readableState,r=e._writableState;n&&n.autoDestroy||r&&r.autoDestroy?e.destroy(t):e.emit(`error`,t)}t.exports={destroy:n,undestroy:a,errorOrDestroy:s}})),S=e(((exports,t)=>{let n={};function r(e,t,r){r||=Error;function i(e,n,r){return typeof t==`string`?t:t(e,n,r)}class a extends r{constructor(e,t,n){super(i(e,t,n))}}a.prototype.name=r.name,a.prototype.code=e,n[e]=a}function i(e,t){if(Array.isArray(e)){let n=e.length;return e=e.map(e=>String(e)),n>2?`one of ${t} ${e.slice(0,n-1).join(`, `)}, or `+e[n-1]:n===2?`one of ${t} ${e[0]} or ${e[1]}`:`of ${t} ${e[0]}`}else return`of ${t} ${String(e)}`}function a(e,t,n){return e.substr(!n||n<0?0:+n,t.length)===t}function o(e,t,n){return(n===void 0||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}function s(e,t,n){return typeof n!=`number`&&(n=0),n+t.length>e.length?!1:e.indexOf(t,n)!==-1}r(`ERR_INVALID_OPT_VALUE`,function(e,t){return`The value "`+t+`" is invalid for option "`+e+`"`},TypeError),r(`ERR_INVALID_ARG_TYPE`,function(e,t,n){let r;typeof t==`string`&&a(t,`not `)?(r=`must not be`,t=t.replace(/^not /,``)):r=`must be`;let c;if(o(e,` argument`))c=`The ${e} ${r} ${i(t,`type`)}`;else{let n=s(e,`.`)?`property`:`argument`;c=`The "${e}" ${n} ${r} ${i(t,`type`)}`}return c+=`. Received type ${typeof n}`,c},TypeError),r(`ERR_STREAM_PUSH_AFTER_EOF`,`stream.push() after EOF`),r(`ERR_METHOD_NOT_IMPLEMENTED`,function(e){return`The `+e+` method is not implemented`}),r(`ERR_STREAM_PREMATURE_CLOSE`,`Premature close`),r(`ERR_STREAM_DESTROYED`,function(e){return`Cannot call `+e+` after a stream was destroyed`}),r(`ERR_MULTIPLE_CALLBACK`,`Callback called multiple times`),r(`ERR_STREAM_CANNOT_PIPE`,`Cannot pipe, not readable`),r(`ERR_STREAM_WRITE_AFTER_END`,`write after end`),r(`ERR_STREAM_NULL_VALUES`,`May not write null values to stream`,TypeError),r(`ERR_UNKNOWN_ENCODING`,function(e){return`Unknown encoding: `+e},TypeError),r(`ERR_STREAM_UNSHIFT_AFTER_END_EVENT`,`stream.unshift() after end event`),t.exports.codes=n})),ne=e(((exports,t)=>{var n=S().codes.ERR_INVALID_OPT_VALUE;function r(e,t,n){return e.highWaterMark==null?t?e[n]:null:e.highWaterMark}function i(e,t,i,a){var o=r(t,a,i);if(o!=null){if(!(isFinite(o)&&Math.floor(o)===o)||o<0)throw new n(a?i:`highWaterMark`,o);return Math.floor(o)}return e.objectMode?16:16*1024}t.exports={getHighWaterMark:i}})),C=e(((exports,t)=>{typeof Object.create==`function`?t.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:t.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}})),w=e(((exports,n)=>{try{var r=t(`util`);if(typeof r.inherits!=`function`)throw``;n.exports=r.inherits}catch{n.exports=C()}})),re=e(((exports,n)=>{function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?r(Object(n),!0).forEach(function(t){a(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function a(e,t,n){return t=l(t),t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){if(!(e instanceof t))throw TypeError(`Cannot call a class as a function`)}function s(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,`value`in r&&(r.writable=!0),Object.defineProperty(e,l(r.key),r)}}function c(e,t,n){return t&&s(e.prototype,t),n&&s(e,n),Object.defineProperty(e,`prototype`,{writable:!1}),e}function l(e){var t=u(e,`string`);return typeof t==`symbol`?t:String(t)}function u(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var d=t(`buffer`),f=d.Buffer,p=t(`util`),m=p.inspect,h=m&&m.custom||`inspect`;function g(e,t,n){f.prototype.copy.call(e,t,n)}n.exports=function(){function e(){o(this,e),this.head=null,this.tail=null,this.length=0}return c(e,[{key:`push`,value:function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}},{key:`unshift`,value:function(e){var t={data:e,next:this.head};this.length===0&&(this.tail=t),this.head=t,++this.length}},{key:`shift`,value:function(){if(this.length!==0){var e=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,e}}},{key:`clear`,value:function(){this.head=this.tail=null,this.length=0}},{key:`join`,value:function(e){if(this.length===0)return``;for(var t=this.head,n=``+t.data;t=t.next;)n+=e+t.data;return n}},{key:`concat`,value:function(e){if(this.length===0)return f.alloc(0);for(var t=f.allocUnsafe(e>>>0),n=this.head,r=0;n;)g(n.data,t,r),r+=n.data.length,n=n.next;return t}},{key:`consume`,value:function(e,t){var n;return e<this.head.data.length?(n=this.head.data.slice(0,e),this.head.data=this.head.data.slice(e)):n=e===this.head.data.length?this.shift():t?this._getString(e):this._getBuffer(e),n}},{key:`first`,value:function(){return this.head.data}},{key:`_getString`,value:function(e){var t=this.head,n=1,r=t.data;for(e-=r.length;t=t.next;){var i=t.data,a=e>i.length?i.length:e;if(a===i.length?r+=i:r+=i.slice(0,e),e-=a,e===0){a===i.length?(++n,t.next?this.head=t.next:this.head=this.tail=null):(this.head=t,t.data=i.slice(a));break}++n}return this.length-=n,r}},{key:`_getBuffer`,value:function(e){var t=f.allocUnsafe(e),n=this.head,r=1;for(n.data.copy(t),e-=n.data.length;n=n.next;){var i=n.data,a=e>i.length?i.length:e;if(i.copy(t,t.length-e,0,a),e-=a,e===0){a===i.length?(++r,n.next?this.head=n.next:this.head=this.tail=null):(this.head=n,n.data=i.slice(a));break}++r}return this.length-=r,t}},{key:h,value:function(e,t){return m(this,i(i({},t),{},{depth:0,customInspect:!1}))}}]),e}()})),T=e(((exports,n)=>{
1
+ import{__commonJSMin as e,__require as t,__toESM as n}from"./chunk-CrDKVgUD.js";import{config as r}from"./env-DRmaf9c0.js";import{arch as i,hostname as a,platform as o}from"node:os";import{join as s,sep as c}from"node:path";import{AsyncLocalStorage as l}from"node:async_hooks";import{randomUUID as u}from"node:crypto";import{chownSync as d,existsSync as f,mkdirSync as p}from"node:fs";import m from"winston";import h from"winston-daily-rotate-file";import{chown as g}from"node:fs/promises";async function _(e){let t=b();if(!t)return;let n=y(e);if(!n){await g(e,t.uid,t.gid);return}for(let e of n)await g(e,t.uid,t.gid)}function v(e){let t=b();if(!t)return;let n=y(e);if(!n){d(e,t.uid,t.gid);return}for(let e of n)d(e,t.uid,t.gid)}function y(e){if(!e.startsWith(c))return;let t=e.split(c),n=t.indexOf(`.onyx`);if(n===-1)return;let r=[];for(let e=n;e<t.length;e++)r.push(t.slice(0,e+1).join(c));return r}function b(){if(typeof process.getuid!=`function`||process.getuid()!==0)return;let e=process.env.SUDO_UID,t=process.env.SUDO_GID;if(!e||!t)return;let n=parseInt(e,10),r=parseInt(t,10);if(!(isNaN(n)||isNaN(r)))return{gid:r,uid:n}}var x=e(((exports,n)=>{n.exports=t(`util`).deprecate})),ee=e(((exports,n)=>{n.exports=t(`stream`)})),te=e(((exports,t)=>{function n(e,t){var n=this,a=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return a||s?(t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(o,this,e)):process.nextTick(o,this,e)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?n._writableState?n._writableState.errorEmitted?process.nextTick(i,n):(n._writableState.errorEmitted=!0,process.nextTick(r,n,e)):process.nextTick(r,n,e):t?(process.nextTick(i,n),t(e)):process.nextTick(i,n)}),this)}function r(e,t){o(e,t),i(e)}function i(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit(`close`)}function a(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function o(e,t){e.emit(`error`,t)}function s(e,t){var n=e._readableState,r=e._writableState;n&&n.autoDestroy||r&&r.autoDestroy?e.destroy(t):e.emit(`error`,t)}t.exports={destroy:n,undestroy:a,errorOrDestroy:s}})),S=e(((exports,t)=>{let n={};function r(e,t,r){r||=Error;function i(e,n,r){return typeof t==`string`?t:t(e,n,r)}class a extends r{constructor(e,t,n){super(i(e,t,n))}}a.prototype.name=r.name,a.prototype.code=e,n[e]=a}function i(e,t){if(Array.isArray(e)){let n=e.length;return e=e.map(e=>String(e)),n>2?`one of ${t} ${e.slice(0,n-1).join(`, `)}, or `+e[n-1]:n===2?`one of ${t} ${e[0]} or ${e[1]}`:`of ${t} ${e[0]}`}else return`of ${t} ${String(e)}`}function a(e,t,n){return e.substr(!n||n<0?0:+n,t.length)===t}function o(e,t,n){return(n===void 0||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}function s(e,t,n){return typeof n!=`number`&&(n=0),n+t.length>e.length?!1:e.indexOf(t,n)!==-1}r(`ERR_INVALID_OPT_VALUE`,function(e,t){return`The value "`+t+`" is invalid for option "`+e+`"`},TypeError),r(`ERR_INVALID_ARG_TYPE`,function(e,t,n){let r;typeof t==`string`&&a(t,`not `)?(r=`must not be`,t=t.replace(/^not /,``)):r=`must be`;let c;if(o(e,` argument`))c=`The ${e} ${r} ${i(t,`type`)}`;else{let n=s(e,`.`)?`property`:`argument`;c=`The "${e}" ${n} ${r} ${i(t,`type`)}`}return c+=`. Received type ${typeof n}`,c},TypeError),r(`ERR_STREAM_PUSH_AFTER_EOF`,`stream.push() after EOF`),r(`ERR_METHOD_NOT_IMPLEMENTED`,function(e){return`The `+e+` method is not implemented`}),r(`ERR_STREAM_PREMATURE_CLOSE`,`Premature close`),r(`ERR_STREAM_DESTROYED`,function(e){return`Cannot call `+e+` after a stream was destroyed`}),r(`ERR_MULTIPLE_CALLBACK`,`Callback called multiple times`),r(`ERR_STREAM_CANNOT_PIPE`,`Cannot pipe, not readable`),r(`ERR_STREAM_WRITE_AFTER_END`,`write after end`),r(`ERR_STREAM_NULL_VALUES`,`May not write null values to stream`,TypeError),r(`ERR_UNKNOWN_ENCODING`,function(e){return`Unknown encoding: `+e},TypeError),r(`ERR_STREAM_UNSHIFT_AFTER_END_EVENT`,`stream.unshift() after end event`),t.exports.codes=n})),ne=e(((exports,t)=>{var n=S().codes.ERR_INVALID_OPT_VALUE;function r(e,t,n){return e.highWaterMark==null?t?e[n]:null:e.highWaterMark}function i(e,t,i,a){var o=r(t,a,i);if(o!=null){if(!(isFinite(o)&&Math.floor(o)===o)||o<0)throw new n(a?i:`highWaterMark`,o);return Math.floor(o)}return e.objectMode?16:16*1024}t.exports={getHighWaterMark:i}})),C=e(((exports,t)=>{typeof Object.create==`function`?t.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:t.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}})),w=e(((exports,n)=>{try{var r=t(`util`);if(typeof r.inherits!=`function`)throw``;n.exports=r.inherits}catch{n.exports=C()}})),re=e(((exports,n)=>{function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?r(Object(n),!0).forEach(function(t){a(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function a(e,t,n){return t=l(t),t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){if(!(e instanceof t))throw TypeError(`Cannot call a class as a function`)}function s(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,`value`in r&&(r.writable=!0),Object.defineProperty(e,l(r.key),r)}}function c(e,t,n){return t&&s(e.prototype,t),n&&s(e,n),Object.defineProperty(e,`prototype`,{writable:!1}),e}function l(e){var t=u(e,`string`);return typeof t==`symbol`?t:String(t)}function u(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var d=t(`buffer`),f=d.Buffer,p=t(`util`),m=p.inspect,h=m&&m.custom||`inspect`;function g(e,t,n){f.prototype.copy.call(e,t,n)}n.exports=function(){function e(){o(this,e),this.head=null,this.tail=null,this.length=0}return c(e,[{key:`push`,value:function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}},{key:`unshift`,value:function(e){var t={data:e,next:this.head};this.length===0&&(this.tail=t),this.head=t,++this.length}},{key:`shift`,value:function(){if(this.length!==0){var e=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,e}}},{key:`clear`,value:function(){this.head=this.tail=null,this.length=0}},{key:`join`,value:function(e){if(this.length===0)return``;for(var t=this.head,n=``+t.data;t=t.next;)n+=e+t.data;return n}},{key:`concat`,value:function(e){if(this.length===0)return f.alloc(0);for(var t=f.allocUnsafe(e>>>0),n=this.head,r=0;n;)g(n.data,t,r),r+=n.data.length,n=n.next;return t}},{key:`consume`,value:function(e,t){var n;return e<this.head.data.length?(n=this.head.data.slice(0,e),this.head.data=this.head.data.slice(e)):n=e===this.head.data.length?this.shift():t?this._getString(e):this._getBuffer(e),n}},{key:`first`,value:function(){return this.head.data}},{key:`_getString`,value:function(e){var t=this.head,n=1,r=t.data;for(e-=r.length;t=t.next;){var i=t.data,a=e>i.length?i.length:e;if(a===i.length?r+=i:r+=i.slice(0,e),e-=a,e===0){a===i.length?(++n,t.next?this.head=t.next:this.head=this.tail=null):(this.head=t,t.data=i.slice(a));break}++n}return this.length-=n,r}},{key:`_getBuffer`,value:function(e){var t=f.allocUnsafe(e),n=this.head,r=1;for(n.data.copy(t),e-=n.data.length;n=n.next;){var i=n.data,a=e>i.length?i.length:e;if(i.copy(t,t.length-e,0,a),e-=a,e===0){a===i.length?(++r,n.next?this.head=n.next:this.head=this.tail=null):(this.head=n,n.data=i.slice(a));break}++r}return this.length-=r,t}},{key:h,value:function(e,t){return m(this,i(i({},t),{},{depth:0,customInspect:!1}))}}]),e}()})),T=e(((exports,n)=>{
2
2
  /*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
3
3
  var r=t(`buffer`),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?n.exports=r:(a(r,exports),exports.Buffer=o);function o(e,t,n){return i(e,t,n)}o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if(typeof e==`number`)throw TypeError(`Argument must not be a number`);return i(e,t,n)},o.alloc=function(e,t,n){if(typeof e!=`number`)throw TypeError(`Argument must be a number`);var r=i(e);return t===void 0?r.fill(0):typeof n==`string`?r.fill(t,n):r.fill(t),r},o.allocUnsafe=function(e){if(typeof e!=`number`)throw TypeError(`Argument must be a number`);return i(e)},o.allocUnsafeSlow=function(e){if(typeof e!=`number`)throw TypeError(`Argument must be a number`);return r.SlowBuffer(e)}})),ie=e((exports=>{var t=T().Buffer,n=t.isEncoding||function(e){switch(e=``+e,e&&e.toLowerCase()){case`hex`:case`utf8`:case`utf-8`:case`ascii`:case`binary`:case`base64`:case`ucs2`:case`ucs-2`:case`utf16le`:case`utf-16le`:case`raw`:return!0;default:return!1}};function r(e){if(!e)return`utf8`;for(var t;;)switch(e){case`utf8`:case`utf-8`:return`utf8`;case`ucs2`:case`ucs-2`:case`utf16le`:case`utf-16le`:return`utf16le`;case`latin1`:case`binary`:return`latin1`;case`base64`:case`ascii`:case`hex`:return e;default:if(t)return;e=(``+e).toLowerCase(),t=!0}}function i(e){var i=r(e);if(typeof i!=`string`&&(t.isEncoding===n||!n(e)))throw Error(`Unknown encoding: `+e);return i||e}exports.StringDecoder=a;function a(e){this.encoding=i(e);var n;switch(this.encoding){case`utf16le`:this.text=f,this.end=p,n=4;break;case`utf8`:this.fillLast=l,n=4;break;case`base64`:this.text=m,this.end=h,n=3;break;default:this.write=g,this.end=_;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=t.allocUnsafe(n)}a.prototype.write=function(e){if(e.length===0)return``;var t,n;if(this.lastNeed){if(t=this.fillLast(e),t===void 0)return``;n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||``},a.prototype.end=d,a.prototype.text=u,a.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length};function o(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e,t,n){var r=t.length-1;if(r<n)return 0;var i=o(t[r]);return i>=0?(i>0&&(e.lastNeed=i-1),i):--r<n||i===-2?0:(i=o(t[r]),i>=0?(i>0&&(e.lastNeed=i-2),i):--r<n||i===-2?0:(i=o(t[r]),i>=0?(i>0&&(i===2?i=0:e.lastNeed=i-3),i):0))}function c(e,t,n){if((t[0]&192)!=128)return e.lastNeed=0,`�`;if(e.lastNeed>1&&t.length>1){if((t[1]&192)!=128)return e.lastNeed=1,`�`;if(e.lastNeed>2&&t.length>2&&(t[2]&192)!=128)return e.lastNeed=2,`�`}}function l(e){var t=this.lastTotal-this.lastNeed,n=c(this,e,t);if(n!==void 0)return n;if(this.lastNeed<=e.length)return e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length}function u(e,t){var n=s(this,e,t);if(!this.lastNeed)return e.toString(`utf8`,t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString(`utf8`,t,r)}function d(e){var t=e&&e.length?this.write(e):``;return this.lastNeed?t+`�`:t}function f(e,t){if((e.length-t)%2==0){var n=e.toString(`utf16le`,t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString(`utf16le`,t,e.length-1)}function p(e){var t=e&&e.length?this.write(e):``;if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString(`utf16le`,0,n)}return t}function m(e,t){var n=(e.length-t)%3;return n===0?e.toString(`base64`,t):(this.lastNeed=3-n,this.lastTotal=3,n===1?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString(`base64`,t,e.length-n))}function h(e){var t=e&&e.length?this.write(e):``;return this.lastNeed?t+this.lastChar.toString(`base64`,0,3-this.lastNeed):t}function g(e){return e.toString(this.encoding)}function _(e){return e&&e.length?this.write(e):``}})),E=e(((exports,t)=>{var n=S().codes.ERR_STREAM_PREMATURE_CLOSE;function r(e){var t=!1;return function(){if(!t){t=!0;var n=[...arguments];e.apply(this,n)}}}function i(){}function a(e){return e.setHeader&&typeof e.abort==`function`}function o(e,t,s){if(typeof t==`function`)return o(e,null,t);t||={},s=r(s||i);var c=t.readable||t.readable!==!1&&e.readable,l=t.writable||t.writable!==!1&&e.writable,u=function(){e.writable||f()},d=e._writableState&&e._writableState.finished,f=function(){l=!1,d=!0,c||s.call(e)},p=e._readableState&&e._readableState.endEmitted,m=function(){c=!1,p=!0,l||s.call(e)},h=function(t){s.call(e,t)},g=function(){var t;if(c&&!p)return(!e._readableState||!e._readableState.ended)&&(t=new n),s.call(e,t);if(l&&!d)return(!e._writableState||!e._writableState.ended)&&(t=new n),s.call(e,t)},_=function(){e.req.on(`finish`,f)};return a(e)?(e.on(`complete`,f),e.on(`abort`,g),e.req?_():e.on(`request`,_)):l&&!e._writableState&&(e.on(`end`,u),e.on(`close`,u)),e.on(`end`,m),e.on(`finish`,f),t.error!==!1&&e.on(`error`,h),e.on(`close`,g),function(){e.removeListener(`complete`,f),e.removeListener(`abort`,g),e.removeListener(`request`,_),e.req&&e.req.removeListener(`finish`,f),e.removeListener(`end`,u),e.removeListener(`close`,u),e.removeListener(`finish`,f),e.removeListener(`end`,m),e.removeListener(`error`,h),e.removeListener(`close`,g)}}t.exports=o})),D=e(((exports,t)=>{var n;function r(e,t,n){return t=i(t),t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){var t=a(e,`string`);return typeof t==`symbol`?t:String(t)}function a(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var o=E(),s=Symbol(`lastResolve`),c=Symbol(`lastReject`),l=Symbol(`error`),u=Symbol(`ended`),d=Symbol(`lastPromise`),f=Symbol(`handlePromise`),p=Symbol(`stream`);function m(e,t){return{value:e,done:t}}function h(e){var t=e[s];if(t!==null){var n=e[p].read();n!==null&&(e[d]=null,e[s]=null,e[c]=null,t(m(n,!1)))}}function g(e){process.nextTick(h,e)}function _(e,t){return function(n,r){e.then(function(){if(t[u]){n(m(void 0,!0));return}t[f](n,r)},r)}}var v=Object.getPrototypeOf(function(){}),y=Object.setPrototypeOf((n={get stream(){return this[p]},next:function(){var e=this,t=this[l];if(t!==null)return Promise.reject(t);if(this[u])return Promise.resolve(m(void 0,!0));if(this[p].destroyed)return new Promise(function(t,n){process.nextTick(function(){e[l]?n(e[l]):t(m(void 0,!0))})});var n=this[d],r;if(n)r=new Promise(_(n,this));else{var i=this[p].read();if(i!==null)return Promise.resolve(m(i,!1));r=new Promise(this[f])}return this[d]=r,r}},r(n,Symbol.asyncIterator,function(){return this}),r(n,`return`,function(){var e=this;return new Promise(function(t,n){e[p].destroy(null,function(e){if(e){n(e);return}t(m(void 0,!0))})})}),n),v);t.exports=function(e){var t,n=Object.create(y,(t={},r(t,p,{value:e,writable:!0}),r(t,s,{value:null,writable:!0}),r(t,c,{value:null,writable:!0}),r(t,l,{value:null,writable:!0}),r(t,u,{value:e._readableState.endEmitted,writable:!0}),r(t,f,{value:function(e,t){var r=n[p].read();r?(n[d]=null,n[s]=null,n[c]=null,e(m(r,!1))):(n[s]=e,n[c]=t)},writable:!0}),t));return n[d]=null,o(e,function(e){if(e&&e.code!==`ERR_STREAM_PREMATURE_CLOSE`){var t=n[c];t!==null&&(n[d]=null,n[s]=null,n[c]=null,t(e)),n[l]=e;return}var r=n[s];r!==null&&(n[d]=null,n[s]=null,n[c]=null,r(m(void 0,!0))),n[u]=!0}),e.on(`readable`,g.bind(null,n)),n}})),O=e(((exports,t)=>{function n(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function r(e){return function(){var t=this,r=arguments;return new Promise(function(i,a){var o=e.apply(t,r);function s(e){n(o,i,a,s,c,`next`,e)}function c(e){n(o,i,a,s,c,`throw`,e)}s(void 0)})}}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?i(Object(n),!0).forEach(function(t){o(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function o(e,t,n){return t=s(t),t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e){var t=c(e,`string`);return typeof t==`symbol`?t:String(t)}function c(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var l=S().codes.ERR_INVALID_ARG_TYPE;function u(e,t,n){var i;if(t&&typeof t.next==`function`)i=t;else if(t&&t[Symbol.asyncIterator])i=t[Symbol.asyncIterator]();else if(t&&t[Symbol.iterator])i=t[Symbol.iterator]();else throw new l(`iterable`,[`Iterable`],t);var o=new e(a({objectMode:!0},n)),s=!1;o._read=function(){s||(s=!0,c())};function c(){return u.apply(this,arguments)}function u(){return u=r(function*(){try{var e=yield i.next(),t=e.value;e.done?o.push(null):o.push(yield t)?c():s=!1}catch(e){o.destroy(e)}}),u.apply(this,arguments)}return o}t.exports=u})),k=e(((exports,n)=>{n.exports=N;var r;N.ReadableState=M,t(`events`).EventEmitter;var i=function(e,t){return e.listeners(t).length},a=ee(),o=t(`buffer`).Buffer,s=(typeof global<`u`?global:typeof window<`u`?window:typeof self<`u`?self:{}).Uint8Array||function(){};function c(e){return o.from(e)}function l(e){return o.isBuffer(e)||e instanceof s}var u=t(`util`),d=u&&u.debuglog?u.debuglog(`stream`):function(){},f=re(),p=te(),m=ne(),h=m.getHighWaterMark,g=S().codes,_=g.ERR_INVALID_ARG_TYPE,v=g.ERR_STREAM_PUSH_AFTER_EOF,y=g.ERR_METHOD_NOT_IMPLEMENTED,b=g.ERR_STREAM_UNSHIFT_AFTER_END_EVENT,x,C,T;w()(N,a);var E=p.errorOrDestroy,k=[`error`,`close`,`destroy`,`pause`,`resume`];function j(e,t,n){if(typeof e.prependListener==`function`)return e.prependListener(t,n);!e._events||!e._events[t]?e.on(t,n):Array.isArray(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]}function M(e,t,n){r||=A(),e||={},typeof n!=`boolean`&&(n=t instanceof r),this.objectMode=!!e.objectMode,n&&(this.objectMode=this.objectMode||!!e.readableObjectMode),this.highWaterMark=h(this,e,`readableHighWaterMark`,n),this.buffer=new f,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=e.emitClose!==!1,this.autoDestroy=!!e.autoDestroy,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||`utf8`,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(x||=ie().StringDecoder,this.decoder=new x(e.encoding),this.encoding=e.encoding)}function N(e){if(r||=A(),!(this instanceof N))return new N(e);var t=this instanceof r;this._readableState=new M(e,this,t),this.readable=!0,e&&(typeof e.read==`function`&&(this._read=e.read),typeof e.destroy==`function`&&(this._destroy=e.destroy)),a.call(this)}Object.defineProperty(N.prototype,`destroyed`,{enumerable:!1,get:function(){return this._readableState===void 0?!1:this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),N.prototype.destroy=p.destroy,N.prototype._undestroy=p.undestroy,N.prototype._destroy=function(e,t){t(e)},N.prototype.push=function(e,t){var n=this._readableState,r;return n.objectMode?r=!0:typeof e==`string`&&(t||=n.defaultEncoding,t!==n.encoding&&(e=o.from(e,t),t=``),r=!0),P(this,e,t,!1,r)},N.prototype.unshift=function(e){return P(this,e,null,!0,!1)};function P(e,t,n,r,i){d(`readableAddChunk`,t);var a=e._readableState;if(t===null)a.reading=!1,B(e,a);else{var s;if(i||(s=I(a,t)),s)E(e,s);else if(a.objectMode||t&&t.length>0)if(typeof t!=`string`&&!a.objectMode&&Object.getPrototypeOf(t)!==o.prototype&&(t=c(t)),r)a.endEmitted?E(e,new b):F(e,a,t,!0);else if(a.ended)E(e,new v);else if(a.destroyed)return!1;else a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||t.length!==0?F(e,a,t,!1):U(e,a)):F(e,a,t,!1);else r||(a.reading=!1,U(e,a))}return!a.ended&&(a.length<a.highWaterMark||a.length===0)}function F(e,t,n,r){t.flowing&&t.length===0&&!t.sync?(t.awaitDrain=0,e.emit(`data`,n)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&V(e)),U(e,t)}function I(e,t){var n;return!l(t)&&typeof t!=`string`&&t!==void 0&&!e.objectMode&&(n=new _(`chunk`,[`string`,`Buffer`,`Uint8Array`],t)),n}N.prototype.isPaused=function(){return this._readableState.flowing===!1},N.prototype.setEncoding=function(e){x||=ie().StringDecoder;var t=new x(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;for(var n=this._readableState.buffer.head,r=``;n!==null;)r+=t.write(n.data),n=n.next;return this._readableState.buffer.clear(),r!==``&&this._readableState.buffer.push(r),this._readableState.length=r.length,this};var L=1073741824;function R(e){return e>=L?e=L:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}function z(e,t){return e<=0||t.length===0&&t.ended?0:t.objectMode?1:e===e?(e>t.highWaterMark&&(t.highWaterMark=R(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0)):t.flowing&&t.length?t.buffer.head.data.length:t.length}N.prototype.read=function(e){d(`read`,e),e=parseInt(e,10);var t=this._readableState,n=e;if(e!==0&&(t.emittedReadable=!1),e===0&&t.needReadable&&((t.highWaterMark===0?t.length>0:t.length>=t.highWaterMark)||t.ended))return d(`read: emitReadable`,t.length,t.ended),t.length===0&&t.ended?Y(this):V(this),null;if(e=z(e,t),e===0&&t.ended)return t.length===0&&Y(this),null;var r=t.needReadable;d(`need readable`,r),(t.length===0||t.length-e<t.highWaterMark)&&(r=!0,d(`length less than watermark`,r)),t.ended||t.reading?(r=!1,d(`reading or ended`,r)):r&&(d(`do read`),t.reading=!0,t.sync=!0,t.length===0&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=z(n,t)));var i=e>0?J(e,t):null;return i===null?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.awaitDrain=0),t.length===0&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&Y(this)),i!==null&&this.emit(`data`,i),i};function B(e,t){if(d(`onEofChunk`),!t.ended){if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,t.sync?V(e):(t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,H(e)))}}function V(e){var t=e._readableState;d(`emitReadable`,t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(d(`emitReadable`,t.flowing),t.emittedReadable=!0,process.nextTick(H,e))}function H(e){var t=e._readableState;d(`emitReadable_`,t.destroyed,t.length,t.ended),!t.destroyed&&(t.length||t.ended)&&(e.emit(`readable`),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,q(e)}function U(e,t){t.readingMore||(t.readingMore=!0,process.nextTick(W,e,t))}function W(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&t.length===0);){var n=t.length;if(d(`maybeReadMore read 0`),e.read(0),n===t.length)break}t.readingMore=!1}N.prototype._read=function(e){E(this,new y(`_read()`))},N.prototype.pipe=function(e,t){var n=this,r=this._readableState;switch(r.pipesCount){case 0:r.pipes=e;break;case 1:r.pipes=[r.pipes,e];break;default:r.pipes.push(e);break}r.pipesCount+=1,d(`pipe count=%d opts=%j`,r.pipesCount,t);var a=(!t||t.end!==!1)&&e!==process.stdout&&e!==process.stderr?s:g;r.endEmitted?process.nextTick(a):n.once(`end`,a),e.on(`unpipe`,o);function o(e,t){d(`onunpipe`),e===n&&t&&t.hasUnpiped===!1&&(t.hasUnpiped=!0,u())}function s(){d(`onend`),e.end()}var c=G(n);e.on(`drain`,c);var l=!1;function u(){d(`cleanup`),e.removeListener(`close`,m),e.removeListener(`finish`,h),e.removeListener(`drain`,c),e.removeListener(`error`,p),e.removeListener(`unpipe`,o),n.removeListener(`end`,s),n.removeListener(`end`,g),n.removeListener(`data`,f),l=!0,r.awaitDrain&&(!e._writableState||e._writableState.needDrain)&&c()}n.on(`data`,f);function f(t){d(`ondata`);var i=e.write(t);d(`dest.write`,i),i===!1&&((r.pipesCount===1&&r.pipes===e||r.pipesCount>1&&ce(r.pipes,e)!==-1)&&!l&&(d(`false write response, pause`,r.awaitDrain),r.awaitDrain++),n.pause())}function p(t){d(`onerror`,t),g(),e.removeListener(`error`,p),i(e,`error`)===0&&E(e,t)}j(e,`error`,p);function m(){e.removeListener(`finish`,h),g()}e.once(`close`,m);function h(){d(`onfinish`),e.removeListener(`close`,m),g()}e.once(`finish`,h);function g(){d(`unpipe`),n.unpipe(e)}return e.emit(`pipe`,n),r.flowing||(d(`pipe resume`),n.resume()),e};function G(e){return function(){var t=e._readableState;d(`pipeOnDrain`,t.awaitDrain),t.awaitDrain&&t.awaitDrain--,t.awaitDrain===0&&i(e,`data`)&&(t.flowing=!0,q(e))}}N.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(t.pipesCount===0)return this;if(t.pipesCount===1)return e&&e!==t.pipes?this:(e||=t.pipes,t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit(`unpipe`,this,n),this);if(!e){var r=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var a=0;a<i;a++)r[a].emit(`unpipe`,this,{hasUnpiped:!1});return this}var o=ce(t.pipes,e);return o===-1?this:(t.pipes.splice(o,1),--t.pipesCount,t.pipesCount===1&&(t.pipes=t.pipes[0]),e.emit(`unpipe`,this,n),this)},N.prototype.on=function(e,t){var n=a.prototype.on.call(this,e,t),r=this._readableState;return e===`data`?(r.readableListening=this.listenerCount(`readable`)>0,r.flowing!==!1&&this.resume()):e===`readable`&&!r.endEmitted&&!r.readableListening&&(r.readableListening=r.needReadable=!0,r.flowing=!1,r.emittedReadable=!1,d(`on readable`,r.length,r.reading),r.length?V(this):r.reading||process.nextTick(ae,this)),n},N.prototype.addListener=N.prototype.on,N.prototype.removeListener=function(e,t){var n=a.prototype.removeListener.call(this,e,t);return e===`readable`&&process.nextTick(K,this),n},N.prototype.removeAllListeners=function(e){var t=a.prototype.removeAllListeners.apply(this,arguments);return(e===`readable`||e===void 0)&&process.nextTick(K,this),t};function K(e){var t=e._readableState;t.readableListening=e.listenerCount(`readable`)>0,t.resumeScheduled&&!t.paused?t.flowing=!0:e.listenerCount(`data`)>0&&e.resume()}function ae(e){d(`readable nexttick read 0`),e.read(0)}N.prototype.resume=function(){var e=this._readableState;return e.flowing||(d(`resume`),e.flowing=!e.readableListening,oe(this,e)),e.paused=!1,this};function oe(e,t){t.resumeScheduled||(t.resumeScheduled=!0,process.nextTick(se,e,t))}function se(e,t){d(`resume`,t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit(`resume`),q(e),t.flowing&&!t.reading&&e.read(0)}N.prototype.pause=function(){return d(`call pause flowing=%j`,this._readableState.flowing),this._readableState.flowing!==!1&&(d(`pause`),this._readableState.flowing=!1,this.emit(`pause`)),this._readableState.paused=!0,this};function q(e){var t=e._readableState;for(d(`flow`,t.flowing);t.flowing&&e.read()!==null;);}N.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var i in e.on(`end`,function(){if(d(`wrapped end`),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)}),e.on(`data`,function(i){d(`wrapped data`),n.decoder&&(i=n.decoder.write(i)),!(n.objectMode&&i==null)&&(!n.objectMode&&(!i||!i.length)||t.push(i)||(r=!0,e.pause()))}),e)this[i]===void 0&&typeof e[i]==`function`&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));for(var a=0;a<k.length;a++)e.on(k[a],this.emit.bind(this,k[a]));return this._read=function(t){d(`wrapped _read`,t),r&&(r=!1,e.resume())},this},typeof Symbol==`function`&&(N.prototype[Symbol.asyncIterator]=function(){return C===void 0&&(C=D()),C(this)}),Object.defineProperty(N.prototype,`readableHighWaterMark`,{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),Object.defineProperty(N.prototype,`readableBuffer`,{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}}),Object.defineProperty(N.prototype,`readableFlowing`,{enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}}),N._fromList=J,Object.defineProperty(N.prototype,`readableLength`,{enumerable:!1,get:function(){return this._readableState.length}});function J(e,t){if(t.length===0)return null;var n;return t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(``):t.buffer.length===1?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):n=t.buffer.consume(e,t.decoder),n}function Y(e){var t=e._readableState;d(`endReadable`,t.endEmitted),t.endEmitted||(t.ended=!0,process.nextTick(X,t,e))}function X(e,t){if(d(`endReadableNT`,e.endEmitted,e.length),!e.endEmitted&&e.length===0&&(e.endEmitted=!0,t.readable=!1,t.emit(`end`),e.autoDestroy)){var n=t._writableState;(!n||n.autoDestroy&&n.finished)&&t.destroy()}}typeof Symbol==`function`&&(N.from=function(e,t){return T===void 0&&(T=O()),T(N,e,t)});function ce(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}})),A=e(((exports,t)=>{var n=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};t.exports=c;var r=k(),i=j();w()(c,r);for(var a=n(i.prototype),o=0;o<a.length;o++){var s=a[o];c.prototype[s]||(c.prototype[s]=i.prototype[s])}function c(e){if(!(this instanceof c))return new c(e);r.call(this,e),i.call(this,e),this.allowHalfOpen=!0,e&&(e.readable===!1&&(this.readable=!1),e.writable===!1&&(this.writable=!1),e.allowHalfOpen===!1&&(this.allowHalfOpen=!1,this.once(`end`,l)))}Object.defineProperty(c.prototype,`writableHighWaterMark`,{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(c.prototype,`writableBuffer`,{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(c.prototype,`writableLength`,{enumerable:!1,get:function(){return this._writableState.length}});function l(){this._writableState.ended||process.nextTick(u,this)}function u(e){e.end()}Object.defineProperty(c.prototype,`destroyed`,{enumerable:!1,get:function(){return this._readableState===void 0||this._writableState===void 0?!1:this._readableState.destroyed&&this._writableState.destroyed},set:function(e){this._readableState===void 0||this._writableState===void 0||(this._readableState.destroyed=e,this._writableState.destroyed=e)}})})),j=e(((exports,n)=>{n.exports=O;function r(e){var t=this;this.next=null,this.entry=null,this.finish=function(){K(t,e)}}var i;O.WritableState=E;var a={deprecate:x()},o=ee(),s=t(`buffer`).Buffer,c=(typeof global<`u`?global:typeof window<`u`?window:typeof self<`u`?self:{}).Uint8Array||function(){};function l(e){return s.from(e)}function u(e){return s.isBuffer(e)||e instanceof c}var d=te(),f=ne(),p=f.getHighWaterMark,m=S().codes,h=m.ERR_INVALID_ARG_TYPE,g=m.ERR_METHOD_NOT_IMPLEMENTED,_=m.ERR_MULTIPLE_CALLBACK,v=m.ERR_STREAM_CANNOT_PIPE,y=m.ERR_STREAM_DESTROYED,b=m.ERR_STREAM_NULL_VALUES,C=m.ERR_STREAM_WRITE_AFTER_END,re=m.ERR_UNKNOWN_ENCODING,T=d.errorOrDestroy;w()(O,o);function ie(){}function E(e,t,n){i||=A(),e||={},typeof n!=`boolean`&&(n=t instanceof i),this.objectMode=!!e.objectMode,n&&(this.objectMode=this.objectMode||!!e.writableObjectMode),this.highWaterMark=p(this,e,`writableHighWaterMark`,n),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1,this.decodeStrings=e.decodeStrings!==!1,this.defaultEncoding=e.defaultEncoding||`utf8`,this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){L(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=e.emitClose!==!1,this.autoDestroy=!!e.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new r(this)}E.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},(function(){try{Object.defineProperty(E.prototype,`buffer`,{get:a.deprecate(function(){return this.getBuffer()},`_writableState.buffer is deprecated. Use _writableState.getBuffer instead.`,`DEP0003`)})}catch{}})();var D;typeof Symbol==`function`&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==`function`?(D=Function.prototype[Symbol.hasInstance],Object.defineProperty(O,Symbol.hasInstance,{value:function(e){return D.call(this,e)?!0:this===O?e&&e._writableState instanceof E:!1}})):D=function(e){return e instanceof this};function O(e){i||=A();var t=this instanceof i;if(!t&&!D.call(O,this))return new O(e);this._writableState=new E(e,this,t),this.writable=!0,e&&(typeof e.write==`function`&&(this._write=e.write),typeof e.writev==`function`&&(this._writev=e.writev),typeof e.destroy==`function`&&(this._destroy=e.destroy),typeof e.final==`function`&&(this._final=e.final)),o.call(this)}O.prototype.pipe=function(){T(this,new v)};function k(e,t){var n=new C;T(e,n),process.nextTick(t,n)}function j(e,t,n,r){var i;return n===null?i=new b:typeof n!=`string`&&!t.objectMode&&(i=new h(`chunk`,[`string`,`Buffer`],n)),i?(T(e,i),process.nextTick(r,i),!1):!0}O.prototype.write=function(e,t,n){var r=this._writableState,i=!1,a=!r.objectMode&&u(e);return a&&!s.isBuffer(e)&&(e=l(e)),typeof t==`function`&&(n=t,t=null),a?t=`buffer`:t||=r.defaultEncoding,typeof n!=`function`&&(n=ie),r.ending?k(this,n):(a||j(this,r,e,n))&&(r.pendingcb++,i=N(this,r,a,e,t,n)),i},O.prototype.cork=function(){this._writableState.corked++},O.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,!e.writing&&!e.corked&&!e.bufferProcessing&&e.bufferedRequest&&B(this,e))},O.prototype.setDefaultEncoding=function(e){if(typeof e==`string`&&(e=e.toLowerCase()),!([`hex`,`utf8`,`utf-8`,`ascii`,`binary`,`base64`,`ucs2`,`ucs-2`,`utf16le`,`utf-16le`,`raw`].indexOf((e+``).toLowerCase())>-1))throw new re(e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(O.prototype,`writableBuffer`,{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function M(e,t,n){return!e.objectMode&&e.decodeStrings!==!1&&typeof t==`string`&&(t=s.from(t,n)),t}Object.defineProperty(O.prototype,`writableHighWaterMark`,{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function N(e,t,n,r,i,a){if(!n){var o=M(t,r,i);r!==o&&(n=!0,i=`buffer`,r=o)}var s=t.objectMode?1:r.length;t.length+=s;var c=t.length<t.highWaterMark;if(c||(t.needDrain=!0),t.writing||t.corked){var l=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:i,isBuf:n,callback:a,next:null},l?l.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else P(e,t,!1,s,r,i,a);return c}function P(e,t,n,r,i,a,o){t.writelen=r,t.writecb=o,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new y(`write`)):n?e._writev(i,t.onwrite):e._write(i,a,t.onwrite),t.sync=!1}function F(e,t,n,r,i){--t.pendingcb,n?(process.nextTick(i,r),process.nextTick(W,e,t),e._writableState.errorEmitted=!0,T(e,r)):(i(r),e._writableState.errorEmitted=!0,T(e,r),W(e,t))}function I(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}function L(e,t){var n=e._writableState,r=n.sync,i=n.writecb;if(typeof i!=`function`)throw new _;if(I(n),t)F(e,n,r,t,i);else{var a=V(n)||e.destroyed;!a&&!n.corked&&!n.bufferProcessing&&n.bufferedRequest&&B(e,n),r?process.nextTick(R,e,n,a,i):R(e,n,a,i)}}function R(e,t,n,r){n||z(e,t),t.pendingcb--,r(),W(e,t)}function z(e,t){t.length===0&&t.needDrain&&(t.needDrain=!1,e.emit(`drain`))}function B(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var i=t.bufferedRequestCount,a=Array(i),o=t.corkedRequestsFree;o.entry=n;for(var s=0,c=!0;n;)a[s]=n,n.isBuf||(c=!1),n=n.next,s+=1;a.allBuffers=c,P(e,t,!0,t.length,a,``,o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new r(t),t.bufferedRequestCount=0}else{for(;n;){var l=n.chunk,u=n.encoding,d=n.callback,f=t.objectMode?1:l.length;if(P(e,t,!1,f,l,u,d),n=n.next,t.bufferedRequestCount--,t.writing)break}n===null&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}O.prototype._write=function(e,t,n){n(new g(`_write()`))},O.prototype._writev=null,O.prototype.end=function(e,t,n){var r=this._writableState;return typeof e==`function`?(n=e,e=null,t=null):typeof t==`function`&&(n=t,t=null),e!=null&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||G(this,r,n),this},Object.defineProperty(O.prototype,`writableLength`,{enumerable:!1,get:function(){return this._writableState.length}});function V(e){return e.ending&&e.length===0&&e.bufferedRequest===null&&!e.finished&&!e.writing}function H(e,t){e._final(function(n){t.pendingcb--,n&&T(e,n),t.prefinished=!0,e.emit(`prefinish`),W(e,t)})}function U(e,t){!t.prefinished&&!t.finalCalled&&(typeof e._final==`function`&&!t.destroyed?(t.pendingcb++,t.finalCalled=!0,process.nextTick(H,e,t)):(t.prefinished=!0,e.emit(`prefinish`)))}function W(e,t){var n=V(t);if(n&&(U(e,t),t.pendingcb===0&&(t.finished=!0,e.emit(`finish`),t.autoDestroy))){var r=e._readableState;(!r||r.autoDestroy&&r.endEmitted)&&e.destroy()}return n}function G(e,t,n){t.ending=!0,W(e,t),n&&(t.finished?process.nextTick(n):e.once(`finish`,n)),t.ended=!0,e.writable=!1}function K(e,t,n){var r=e.entry;for(e.entry=null;r;){var i=r.callback;t.pendingcb--,i(n),r=r.next}t.corkedRequestsFree.next=e}Object.defineProperty(O.prototype,`destroyed`,{enumerable:!1,get:function(){return this._writableState===void 0?!1:this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),O.prototype.destroy=d.destroy,O.prototype._undestroy=d.undestroy,O.prototype._destroy=function(e,t){t(e)}})),M=e((exports=>{exports.levels={error:0,warn:1,help:2,data:3,info:4,debug:5,prompt:6,verbose:7,input:8,silly:9},exports.colors={error:`red`,warn:`yellow`,help:`cyan`,data:`grey`,info:`green`,debug:`blue`,prompt:`grey`,verbose:`cyan`,input:`grey`,silly:`magenta`}})),N=e((exports=>{exports.levels={error:0,warn:1,info:2,http:3,verbose:4,debug:5,silly:6},exports.colors={error:`red`,warn:`yellow`,info:`green`,http:`green`,verbose:`cyan`,debug:`blue`,silly:`magenta`}})),P=e((exports=>{exports.levels={emerg:0,alert:1,crit:2,error:3,warning:4,notice:5,info:6,debug:7},exports.colors={emerg:`red`,alert:`yellow`,crit:`red`,error:`red`,warning:`red`,notice:`yellow`,info:`green`,debug:`blue`}})),F=e((exports=>{Object.defineProperty(exports,`cli`,{value:M()}),Object.defineProperty(exports,`npm`,{value:N()}),Object.defineProperty(exports,`syslog`,{value:P()})})),I=e((exports=>{Object.defineProperty(exports,`LEVEL`,{value:Symbol.for(`level`)}),Object.defineProperty(exports,`MESSAGE`,{value:Symbol.for(`message`)}),Object.defineProperty(exports,`SPLAT`,{value:Symbol.for(`splat`)}),Object.defineProperty(exports,`configs`,{value:F()})})),L=e(((exports,n)=>{let r=t(`util`),i=j(),{LEVEL:a}=I(),o=n.exports=function(e={}){i.call(this,{objectMode:!0,highWaterMark:e.highWaterMark}),this.format=e.format,this.level=e.level,this.handleExceptions=e.handleExceptions,this.handleRejections=e.handleRejections,this.silent=e.silent,e.log&&(this.log=e.log),e.logv&&(this.logv=e.logv),e.close&&(this.close=e.close),this.once(`pipe`,e=>{this.levels=e.levels,this.parent=e}),this.once(`unpipe`,e=>{e===this.parent&&(this.parent=null,this.close&&this.close())})};r.inherits(o,i),o.prototype._write=function(e,t,n){if(this.silent||e.exception===!0&&!this.handleExceptions)return n(null);let r=this.level||this.parent&&this.parent.level;if(!r||this.levels[r]>=this.levels[e[a]]){if(e&&!this.format)return this.log(e,n);let t,r;try{r=this.format.transform(Object.assign({},e),this.format.options)}catch(e){t=e}if(t||!r){if(n(),t)throw t;return}return this.log(r,n)}return this._writableState.sync=!1,n(null)},o.prototype._writev=function(e,t){if(this.logv){let n=e.filter(this._accept,this);return n.length?this.logv(n,t):t(null)}for(let n=0;n<e.length;n++){if(!this._accept(e[n]))continue;if(e[n].chunk&&!this.format){this.log(e[n].chunk,e[n].callback);continue}let r,i;try{i=this.format.transform(Object.assign({},e[n].chunk),this.format.options)}catch(e){r=e}if(r||!i){if(e[n].callback(),r)throw t(null),r}else this.log(i,e[n].callback)}return t(null)},o.prototype._accept=function(e){let t=e.chunk;if(this.silent)return!1;let n=this.level||this.parent&&this.parent.level;return!!((t.exception===!0||!n||this.levels[n]>=this.levels[t[a]])&&(this.handleExceptions||t.exception!==!0))},o.prototype._nop=function(){}})),R=e(((exports,n)=>{let r=t(`util`),{LEVEL:i}=I(),a=L(),o=n.exports=function(e={}){if(a.call(this,e),!e.transport||typeof e.transport.log!=`function`)throw Error(`Invalid transport, must be an object with a log method.`);this.transport=e.transport,this.level=this.level||e.transport.level,this.handleExceptions=this.handleExceptions||e.transport.handleExceptions,this._deprecated();function t(e){this.emit(`error`,e,this.transport)}this.transport.__winstonError||(this.transport.__winstonError=t.bind(this),this.transport.on(`error`,this.transport.__winstonError))};r.inherits(o,a),o.prototype._write=function(e,t,n){if(this.silent||e.exception===!0&&!this.handleExceptions)return n(null);(!this.level||this.levels[this.level]>=this.levels[e[i]])&&this.transport.log(e[i],e.message,e,this._nop),n(null)},o.prototype._writev=function(e,t){for(let t=0;t<e.length;t++)this._accept(e[t])&&(this.transport.log(e[t].chunk[i],e[t].chunk.message,e[t].chunk,this._nop),e[t].callback());return t(null)},o.prototype._deprecated=function(){console.error([`${this.transport.name} is a legacy winston transport. Consider upgrading: `,`- Upgrade docs: https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md`].join(`
4
4
  `))},o.prototype.close=function(){this.transport.close&&this.transport.close(),this.transport.__winstonError&&(this.transport.removeListener(`error`,this.transport.__winstonError),this.transport.__winstonError=null)}})),z=n(e(((exports,t)=>{t.exports=L(),t.exports.LegacyTransportStream=R()}))(),1);const B=new Set([`apikey`,`auth`,`credential`,`key`,`password`,`secret`,`token`]);var V=class extends z.default{apiKey;extraAttributes;httpTimeout;ingestUrl;pendingRequests=new Set;constructor(e){super({}),this.apiKey=e.apiKey,this.ingestUrl=e.ingestUrl,this.httpTimeout=e.httpTimeout??5e3;let t=a()||`unknown`;this.extraAttributes={arch:i(),hostname:t,instance:`mcp-gateway-${t}`,os:o(),source:`onyx-mcp-gateway`,version:r.appVersion,workload:`mcp-gateway`}}async flush(e=5e3){let t=Array.from(this.pendingRequests);t.length!==0&&await Promise.race([Promise.all(t),new Promise(t=>setTimeout(t,e))])}log(e,t){setImmediate(()=>this.emit(`logged`,e));let n=this.enrichEntry(e),r=this.sendEntry(n);this.pendingRequests.add(r),r.finally(()=>this.pendingRequests.delete(r)),t()}enrichEntry(e){let t={...this.extraAttributes,level:(e.level||`info`).toUpperCase(),message:e.message||``,timestamp:e.timestamp||new Date().toISOString()};for(let[n,r]of Object.entries(e)){if([`level`,`message`,`timestamp`].includes(n))continue;B.has(n.toLowerCase())?t[n]=`[REDACTED]`:t[n]=U(r)}return t}async sendEntry(e){let t=new AbortController,n=setTimeout(()=>t.abort(),this.httpTimeout);try{let n=H(e);await(await fetch(this.ingestUrl,{body:n,headers:{apikey:this.apiKey,"Content-Type":`application/json`,"x-source-type":`endpoint-logs`},method:`POST`,signal:t.signal})).text()}catch{}finally{clearTimeout(n)}}};function H(e){try{return JSON.stringify(e)}catch(t){let n={_serializationError:!0,level:`ERROR`,message:`[Log entry could not be serialized]`,originalError:t instanceof Error?t.message:String(t),timestamp:new Date().toISOString()};if(e&&typeof e==`object`)for(let t of[`level`,`message`,`timestamp`,`source`,`workload`]){let r=e[t];typeof r==`string`&&(n[t]=r)}return JSON.stringify(n)}}function U(e,t=0,n=new WeakSet){if(t>10)return`[max depth exceeded]`;if(e==null)return e;let r=typeof e;if(r===`string`||r===`number`||r===`boolean`)return r===`number`&&(Number.isNaN(e)||!Number.isFinite(e))?String(e):e;if(r===`function`)return`[Function: ${e.name||`anonymous`}]`;if(r===`symbol`)return`[Symbol: ${e.description||``}]`;if(r===`bigint`)return String(e);if(r===`object`){if(n.has(e))return`[Circular]`;if(n.add(e),e instanceof Date)return e.toISOString();if(e instanceof Error)return{message:e.message,name:e.name,stack:e.stack};if(e instanceof RegExp)return e.toString();if(e instanceof Map){let r={};for(let[i,a]of e){let e=typeof i==`string`?i:String(i);r[e]=U(a,t+1,n)}return r}if(e instanceof Set)return Array.from(e).map(e=>U(e,t+1,n));if(Array.isArray(e))return e.map(e=>U(e,t+1,n));if(ArrayBuffer.isView(e)||e instanceof ArrayBuffer)return`[Binary Data]`;let r={},i;try{i=Object.keys(e)}catch{return`[Object with inaccessible keys]`}for(let a of i){if(B.has(a.toLowerCase())){r[a]=`[REDACTED]`;continue}try{let i=e[a];r[a]=U(i,t+1,n)}catch{r[a]=`[Unserializable]`}}return r}return`[Unknown Type]`}const W=u(),G=new l;function K(e,t){return G.run({traceId:e},t)}let ae=W;function oe(e){let t=e?.traceparent;if(t){let e=t.split(`-`);if(e.length>=2&&e[1])return e[1]}}function se(){return G.getStore()?.traceId??ae}function q(e){ae=e}const J=r.logDir,Y=r.debug?`debug`:`info`;let X=!1;try{f(J)||p(J,{recursive:!0}),X=!0;try{v(J)}catch{}}catch(e){let t=e instanceof Error?e.message:String(e),n=t.includes(`EACCES`)||t.includes(`permission denied`);console.error(`[mcp-gateway] WARNING: Failed to create log directory: ${J}`),console.error(`[mcp-gateway] Error: ${t}`),n&&(console.error(`[mcp-gateway] This appears to be a permission issue. Possible solutions:`),console.error(`[mcp-gateway] 1. Fix directory permissions: sudo chown -R $USER ~/.onyx`),console.error(`[mcp-gateway] 2. Use a different log directory: export MCP_GATEWAY_LOG_DIR=/tmp/mcp-gateway-logs`)),console.error(`[mcp-gateway] File logging will be disabled. The gateway will continue to function.`)}const ce=m.format.combine(m.format.timestamp(),m.format.errors({stack:!0}),m.format.json());let Z=null;const le=[];let ue=null;X&&(ue=new h({datePattern:`YYYY-MM-DD`,filename:s(J,`mcp-gateway-%DATE%.log`),format:ce,handleExceptions:!1,handleRejections:!1,level:Y,maxFiles:10,maxSize:`10m`}),le.push(ue));let Q=null;const de=r.logIngest.enabled&&r.logIngest.url&&r.logIngest.apiKey;de&&(Q=new V({apiKey:r.logIngest.apiKey,httpTimeout:r.logIngest.timeoutMs,ingestUrl:r.logIngest.url}),le.push(Q));const fe=m.format(e=>(e.traceId=se(),e)),$=m.createLogger({defaultMeta:{service:`mcp-gateway`,version:r.appVersion},format:m.format.combine(fe(),m.format.errors({stack:!0})),level:Y,transports:le}),pe=e=>{let[t,...n]=e;if(typeof t!=`string`)return{message:String(t??``),meta:void 0,sessionData:Z||void 0};if(n.length>0&&n[0]&&typeof n[0]==`object`&&`proxyType`in n[0]){let e=n[0],r=n[1];return{message:t,meta:r,sessionData:e}}let r=n[0];return{message:t,meta:r,sessionData:Z||void 0}},me={debug:(...e)=>{let{message:t,meta:n,sessionData:r}=pe(e);$.debug(t,{sessionData:r,...n})},error:(...e)=>{let{message:t,meta:n,sessionData:r}=pe(e);$.error(t,{sessionData:r,...n})},getSessionData:()=>Z,getTraceId:()=>se(),info:(...e)=>{let{message:t,meta:n,sessionData:r}=pe(e);$.info(t,{sessionData:r,...n})},setSessionData:e=>{Z=e,me.debug(`Session data set for logger`,e)},setTraceId:e=>{q(e),me.debug(`Trace ID updated for logger`,{traceId:e})},warn:(...e)=>{let{message:t,meta:n,sessionData:r}=pe(e);$.warn(t,{sessionData:r,...n})}};let he=null;const ge=e=>he||(he=(async()=>{let t=[];Q&&t.push(Q.flush(e)),ue?t.push(new Promise(t=>{let n=!1,r=()=>{n||(n=!0,t())};setTimeout(()=>{$.once(`finish`,r),$.once(`error`,r),$.end()},50).unref(),e&&e>0&&setTimeout(r,e).unref()})):t.push(new Promise(e=>setImmediate(e))),await Promise.all(t)})(),he);me.info(`MCP Gateway logger initialized`,{debug:r.debug,fileLoggingEnabled:X,ingestLoggingEnabled:de,logDir:J,logLevel:Y});export{_ as chownToRealUser,oe as extractTraceIdFromHeaders,ge as flushLogs,W as gatewayCorrelationId,me as logger,w as require_inherits,K as runWithTraceContextAsync};
5
- //# sourceMappingURL=logger-DSLFCg6q.js.map
5
+ //# sourceMappingURL=logger-ztMIFOl1.js.map