@agimon-ai/po-mcp-proxy 0.0.1-alpha.2 → 0.0.1-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.mjs +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +33 -2
- package/dist/index.d.mts +33 -2
- package/dist/index.mjs +1 -1
- package/dist/src-BANc8nJN.mjs +72 -0
- package/dist/src-BKuGg3Ob.cjs +72 -0
- package/package.json +9 -7
- package/dist/src-Bq40B1Wm.cjs +0 -72
- package/dist/src-Crejf8_V.mjs +0 -72
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{X as CALLBACK_BIND_WAIT_MS,Z as CALLBACK_POLL_INTERVAL_MS,Q as CALLBACK_PORT_SPAN,$ as CALLBACK_TIMEOUT_MS,ct as CallbackRendezvous,R as ConfigFetcherService,et as DEFAULT_CALLBACK_PATH,tt as DEFAULT_CALLBACK_PORT,g as DEFAULT_HTTP_RUNTIME_TIMEOUT_MS,j as DefinitionsCacheService,m as DescribeToolsTool,G as FileTokenStore,S as HttpTransportHandler,E as McpClientManagerService,W as McpOAuthProvider,K as MemoryTokenStore,nt as OAuthCallbackServer,O as OutputGuardService,lt as RESERVATION_STALE_MS,T as RuntimeStateService,p as SearchListToolsTool,w as SkillService,u as StdioHttpTransportHandler,d as StdioTransportHandler,C as StopServerService,t as TRANSPORT_MODE,f as UseToolTool,rt as acquireSharedCallbackServer,M as cleanupStaleRegistries,it as closeSharedCallbackServer,F as collectConfigPath,i as createHttpTransportHandler,B as createOAuthProvider,a as createProxyContainer,o as createProxyIoCContainer,A as createProxyLogger,n as createServer,r as createSessionServer,s as createStdioHttpTransportHandler,c as createStdioTransportHandler,P as findConfigFile,_ as findHealthyExistingRuntime,N as generateServerId,ut as getDefaultRendezvousRoot,q as getDefaultTokenStoreDir,at as getSharedCallbackServer,l as initializeSharedServices,D as isAuthError,z as parseMcpConfig,y as prestartHttpRuntime,b as probeRuntimeHealth,J as readAuthEntryForUrl,ot as releaseSharedCallbackServer,V as resolveAuthScheme,H as resolveBearerToken,U as resolveCallbackPort,k as resolveOutputGuardOptions,dt as resolveWorkspaceRoot,I as toConfigPaths,L as toConfigSources,Y as withTokenStoreLock,st as workspaceCallbackPort}from"./src-BANc8nJN.mjs";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import{existsSync as e}from"node:fs";import t,{dirname as n,isAbsolute as r,join as i,resolve as a}from"node:path";import{createCipheriv as o,createDecipheriv as s,createHash as c,randomBytes as l,randomUUID as u,timingSafeEqual as d}from"node:crypto";import{createServer as f}from"node:http";import{access as p,chmod as m,lstat as h,mkdir as g,mkdtemp as _,open as v,readFile as y,readdir as b,rename as x,rm as S,stat as C,unlink as w,utimes as ee,watch as te,writeFile as T}from"node:fs/promises";import{homedir as E,tmpdir as ne}from"node:os";import{lock as re}from"proper-lockfile";import{spawn as ie}from"node:child_process";import{fileURLToPath as ae}from"node:url";import{PROCESS_REGISTRY_OWNER_ID_ENV_VAR as oe,PROCESS_REGISTRY_OWNER_KIND_ENV_VAR as se,ProcessRegistryService as ce,createProcessLease as le,resolveSiblingRegistryPath as ue}from"@agimon-ai/foundation-process-registry";import*as D from"js-yaml";import{z as O}from"zod";import{METHOD_NOT_FOUND as de,ProtocolError as fe,Server as pe,createMcpHandler as me}from"@modelcontextprotocol/server";import{PortRegistryService as he}from"@agimon-ai/foundation-port-registry";import{createNodeTelemetry as ge}from"@agimon-ai/po-logsink/telemetry/node";import{setTimeout as _e}from"node:timers/promises";import{Client as ve,InsufficientScopeError as ye,ProtocolError as be,ProtocolErrorCode as xe,SSEClientTransport as Se,StreamableHTTPClientTransport as Ce,UnauthorizedError as k,auth as we,computeScopeUnion as Te,extractWWWAuthenticateParams as Ee,isCallToolResult as De,validateAuthorizationResponseIssuer as Oe}from"@modelcontextprotocol/client";import{StdioClientTransport as ke}from"@modelcontextprotocol/client/stdio";import{AsyncLocalStorage as Ae}from"node:async_hooks";import{AjvJsonSchemaValidator as je}from"@modelcontextprotocol/client/validators/ajv";import{once as Me}from"node:events";import{inspect as Ne,promisify as Pe}from"node:util";import{getRequestListener as Fe}from"@hono/node-server";import{toNodeHandler as Ie}from"@modelcontextprotocol/node";import{Hono as Le}from"hono";import{Liquid as Re}from"liquidjs";import{coerceArgs as A,formatZodError as ze,jsonSchemaToZod as Be}from"@agimon-ai/foundation-validator";import{serveStdio as Ve}from"@modelcontextprotocol/server/stdio";const He=[`pnpm-workspace.yaml`,`nx.json`,`.git`];function j(n=process.env.PROJECT_PATH||process.cwd()){let r=t.resolve(n);for(;;){for(let n of He)if(e(t.join(r,n)))return r;let i=t.dirname(r);if(i===r)return t.resolve(n);r=i}}const Ue=`host.json`,M=`.reserved`,N=`.result`,We=6e4;function Ge(e){try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function Ke(e){return e.replace(/[^\x20-\x7E]/g,``).slice(0,200)}function qe(){return i(E(),`.mcp-proxy`,`callbacks`)}var Je=class e{root;isPidAlive;constructor(e={}){this.root=e.root??qe(),this.isPidAlive=e.isPidAlive??Ge}directoryFor(e){return i(this.root,String(e))}static keyFor(e){return c(`sha256`).update(e,`utf8`).digest(`hex`)}async ensureDirectory(e){let t=this.directoryFor(e);return await g(t,{recursive:!0,mode:448}),t}async publish(e,t,n){let r=i(e,`.${t}.${l(6).toString(`hex`)}`);await T(r,JSON.stringify(n),{encoding:`utf-8`,mode:384});try{await x(r,i(e,t))}catch(e){throw await S(r,{force:!0}).catch(()=>void 0),e}}async readJson(e){try{return JSON.parse(await y(e,`utf-8`))}catch{return}}async claimHost(e){let t=await this.ensureDirectory(e),n={pid:process.pid,startedAt:(/* @__PURE__ */ new Date()).toISOString()};await this.publish(t,Ue,n)}async releaseHost(e){await S(i(this.directoryFor(e),Ue),{force:!0}).catch(()=>void 0)}async readHost(e){let t=await this.readJson(i(this.directoryFor(e),Ue));if(t&&typeof t.pid==`number`)return this.isPidAlive(t.pid)?t:void 0}async reserve(t,n){let r=await this.ensureDirectory(t),i={pid:process.pid};await this.publish(r,`${e.keyFor(n)}${M}`,i)}async heartbeat(t,n){let r=i(this.directoryFor(t),`${e.keyFor(n)}${M}`),a=/* @__PURE__ */ new Date;await ee(r,a,a).catch(()=>void 0)}async release(t,n){let r=e.keyFor(n),a=this.directoryFor(t);await Promise.all([S(i(a,`${r}${M}`),{force:!0}).catch(()=>void 0),S(i(a,`${r}${N}`),{force:!0}).catch(()=>void 0)])}async hasReservation(t,n){let r=i(this.directoryFor(t),`${e.keyFor(n)}${M}`);return this.isReservationLive(r)}async hasLiveReservations(e){let t=this.directoryFor(e),n;try{n=await b(t)}catch{return!1}for(let e of n)if(e.endsWith(M)&&await this.isReservationLive(i(t,e)))return!0;return!1}async isReservationLive(e){let t=await this.readJson(e);if(!t||typeof t.pid!=`number`||!this.isPidAlive(t.pid))return!1;try{let t=await C(e);return Date.now()-t.mtimeMs<We}catch{return!1}}async bank(t,n,r){let i=await this.ensureDirectory(t),a=r.status===`denied`?{status:`denied`,error:Ke(r.error)}:r;await this.publish(i,`${e.keyFor(n)}${N}`,a)}async takeResult(t,n){let r=i(this.directoryFor(t),`${e.keyFor(n)}${N}`),a=await this.readJson(r);if(a&&typeof a.status==`string`)return await S(r,{force:!0}).catch(()=>void 0),a}async collectGarbage(e){let t=this.directoryFor(e),n;try{n=await b(t)}catch{return}for(let e of n){if(e.endsWith(M)){if(!await this.isReservationLive(i(t,e))){await S(i(t,e),{force:!0}).catch(()=>void 0);let n=e.slice(0,-9);await S(i(t,`${n}${N}`),{force:!0}).catch(()=>void 0)}continue}if(!e.endsWith(N))continue;let n=e.slice(0,-7);await this.isReservationLive(i(t,`${n}${M}`))||await S(i(t,e),{force:!0}).catch(()=>void 0)}}};const Ye=19876,Xe=100;function Ze(e){let t=c(`sha256`).update(e).digest();return Ye+t.readUInt16BE(0)%100}const Qe=`/callback`,$e=3e5,et=6e4,tt=250,nt={"content-type":`text/html; charset=utf-8`};function rt(e){return`Authorization failed: ${e}`}function it(e,t){return`<!doctype html><meta charset="utf-8"><title>${e}</title><body style="font-family:system-ui;padding:2rem"><h1>${e}</h1><p>${t}</p></body>`}function at(e){return e?.code===`EADDRINUSE`}function ot(e){return new Promise(t=>{setTimeout(t,e).unref?.()})}var st=class{server;boundPort;requestedPort;guestPort;closing=!1;listening;pending=/* @__PURE__ */ new Map;path;rendezvous;pollIntervalMs;bindWaitMs;constructor(e=Qe){let t=typeof e==`string`?{path:e}:e;this.path=t.path??`/callback`,this.rendezvous=t.rendezvous===!1?void 0:new Je(t),this.pollIntervalMs=t.pollIntervalMs??250,this.bindWaitMs=t.bindWaitMs??6e4}getPort(){return this.boundPort}getRedirectPort(){return this.boundPort??this.guestPort}hasPendingAuthorizations(){return this.pending.size>0}async listen(e){let t=this.listening;if(t){if(t.port===e)return t.promise;await t.promise.catch(()=>void 0)}let n=this.acquire(e);this.listening={port:e,promise:n};try{return await n}finally{this.listening?.promise===n&&(this.listening=void 0)}}async acquire(e){let t=this.getRedirectPort();if(t!==void 0){if(e!==0&&e!==t){if(this.hasPendingAuthorizations())throw Error(`OAuth callback server is bound to port ${t} with an authorization in progress; cannot rebind to ${e}.`);await this.close()}else if(this.server||this.guestPort!==void 0)return t}let n=Date.now()+this.bindWaitMs;for(;;)try{return await this.bind(e)}catch(t){if(e===0||!at(t))throw t;if(await this.rendezvous?.readHost(e))return this.guestPort=e,e;if(Date.now()>=n)throw Error(`OAuth callback port ${e} is held by another process that cannot forward callbacks. Waited ${Math.round(this.bindWaitMs/1e3)}s for it to be released. Finish or cancel the other authorization, or set this server's oauth.redirectUri to a different port.`);await ot(this.pollIntervalMs)}}async bind(e){let t=f((t,n)=>{this.handleRequest(t.url??`/`,e,n)});await new Promise((n,r)=>{t.once(`error`,r),t.listen(e,`127.0.0.1`,()=>{t.removeListener(`error`,r),n()})});let n=t.address();if(n===null||typeof n==`string`)throw t.close(),Error(`OAuth callback server failed to report a bound port.`);return t.unref(),this.server=t,this.boundPort=n.port,this.requestedPort=e,this.guestPort=void 0,e!==0&&(await this.rendezvous?.claimHost(this.boundPort).catch(()=>void 0),await this.rendezvous?.collectGarbage(this.boundPort).catch(()=>void 0),await this.adoptOwnReservations(this.boundPort)),this.boundPort}async adoptOwnReservations(e){for(let[t,n]of this.pending)n.guest&&(n.guest.poll&&clearTimeout(n.guest.poll),n.guest=void 0,await this.rendezvous?.release(e,t).catch(()=>void 0))}async handleRequest(e,t,n){let r=new URL(e,`http://localhost:${this.boundPort??t}`);if(r.pathname!==this.path){n.writeHead(404,nt).end(it(`Not found`,`Unexpected callback path.`));return}let i=r.searchParams.get(`state`)??``,a=r.searchParams.get(`error`),o=r.searchParams.get(`code`),s=r.searchParams.get(`iss`),c=a?{status:`denied`,error:a}:o?{status:`ok`,code:o,...s===null?{}:{iss:s}}:{status:`malformed`};if(this.pending.has(i)){this.settleOutcome(i,c),this.respond(n,c);return}let l=this.boundPort;l!==void 0&&i&&await this.rendezvous?.hasReservation(l,i)?(await this.rendezvous?.bank(l,i,c).catch(()=>void 0),this.respond(n,c)):n.writeHead(400,nt).end(it(`Invalid request`,`This authorization request is not recognised.`))}respond(e,t){if(t.status===`ok`){e.writeHead(200,nt).end(it(`Authorized`,`You can close this window and return to your terminal.`));return}let n=t.status===`denied`?`You can close this window.`:`No authorization code was returned.`;e.writeHead(400,nt).end(it(`Authorization failed`,n))}settleOutcome(e,t){if(t.status===`ok`){this.settle(e,{code:t.code,state:e,...t.iss===void 0?{}:{iss:t.iss}});return}let n=t.status===`denied`?rt(t.error):`Authorization response did not include a code.`;this.settle(e,void 0,Error(n))}async reserve(e,t=$e){if(this.pending.has(e))throw Error(`An authorization with this state is already pending.`);let n=this.server?void 0:this.guestPort;n!==void 0&&await this.rendezvous?.reserve(n,e);let r=this.register(e,t);n!==void 0&&(r.guest={port:n,poll:void 0},this.scheduleGuestPoll(e,r))}waitForCallback(e,t=$e){let n=this.pending.get(e);if(n)return n.claimed?Promise.reject(/* @__PURE__ */ Error(`An authorization with this state is already pending.`)):(n.claimed=!0,n.promise);if(!this.server&&this.guestPort!==void 0)return Promise.reject(/* @__PURE__ */ Error(`This process does not own the OAuth callback port; reserve the state before waiting on it.`));let r=this.register(e,t);return r.claimed=!0,r.promise}register(e,t){let n,r=new Promise((r,i)=>{let a=setTimeout(()=>{this.abandon(e,Error(this.timeoutMessage(e,t)))},t);a.unref?.(),n={resolve:r,reject:i,timer:a}});return n.promise=r,r.catch(()=>void 0),this.pending.set(e,n),n}timeoutMessage(e,t){let n=Math.round(t/1e3);return this.pending.get(e)?.guest?`Timed out after ${n}s waiting for the OAuth redirect. Another process was receiving it and may have exited; reload the redirect page in your browser or start the authorization again.`:`Timed out after ${n}s waiting for the OAuth redirect.`}cancel(e){this.abandon(e,/* @__PURE__ */ Error(`Authorization cancelled.`))}async abandon(e,t){let n=this.pending.get(e)?.guest;this.settle(e,void 0,t),n&&await this.rendezvous?.release(n.port,e).catch(()=>void 0)}settle(e,t,n){let r=this.pending.get(e);r&&(clearTimeout(r.timer),r.guest?.poll&&clearTimeout(r.guest.poll),this.pending.delete(e),n?r.reject(n):t&&r.resolve(t),this.releaseWhenIdle())}scheduleGuestPoll(e,t){let n=t.guest;if(!n)return;let r=setTimeout(()=>{this.pollAsGuest(e)},this.pollIntervalMs);r.unref?.(),n.poll=r}async tryPromote(e){if(this.server)return!0;let t=this.listening;if(t)return await t.promise.catch(()=>void 0),this.server!==void 0;let n=this.bind(e);this.listening={port:e,promise:n};try{return await n,!0}catch{return!1}finally{this.listening?.promise===n&&(this.listening=void 0)}}async pollAsGuest(e){let t=this.pending.get(e),n=t?.guest;if(!t||!n)return;let r=await this.rendezvous?.takeResult(n.port,e).catch(()=>void 0);r?(this.settleOutcome(e,r),await this.rendezvous?.release(n.port,e).catch(()=>void 0)):(await this.tryPromote(n.port),this.pending.get(e)?.guest&&(await this.rendezvous?.heartbeat(n.port,e).catch(()=>void 0),this.scheduleGuestPoll(e,t)))}async releaseWhenIdle(){if(this.closing||!this.server||this.pending.size>0||this.requestedPort===0)return;let e=this.boundPort;e!==void 0&&await this.rendezvous?.hasLiveReservations(e).catch(()=>!1)||this.closing||!this.server||this.pending.size>0||await this.close()}async close(){this.closing=!0;try{for(let e of Array.from(this.pending.keys()))await this.abandon(e,/* @__PURE__ */ Error(`OAuth callback server shut down.`));let e=this.server,t=this.boundPort;if(this.server=void 0,this.boundPort=void 0,this.requestedPort=void 0,this.guestPort=void 0,t!==void 0&&await this.rendezvous?.releaseHost(t).catch(()=>void 0),!e)return;await new Promise(t=>{e.close(()=>t())})}finally{this.closing=!1}}};let P,F=0;function ct(){return P??=new st,P}function lt(){return F+=1,ct()}async function ut(){F>0&&--F,!(F>0)&&(P?.hasPendingAuthorizations()||await dt())}async function dt(){let e=P;P=void 0,F=0,await e?.close()}const ft=/* @__PURE__ */ new WeakMap;async function pt(e,t,n,r){return e.withLock?e.withLock(t,n,r):mt(e,t,n,r)}async function mt(e,t,n,r){let i=ft.get(e);i||ft.set(e,i=/* @__PURE__ */ new Map);let a=i.get(t)??Promise.resolve(),o,s=new Promise(e=>{o=e});i.set(t,s),await a;try{return r?.throwIfAborted(),await n()}finally{o(),i.get(t)===s&&i.delete(t)}}function ht(){return i(E(),`.mcp-proxy`,`oauth`)}function gt(e){return`sha256-${c(`sha256`).update(e,`utf8`).digest(`hex`)}`}function _t(e,t){let n=l(12),r=o(`aes-256-gcm`,t,n),i=Buffer.concat([r.update(JSON.stringify(e),`utf8`),r.final()]);return{version:1,iv:n.toString(`base64`),tag:r.getAuthTag().toString(`base64`),ciphertext:i.toString(`base64`)}}function vt(e,t){let n=JSON.parse(e);if(!n||typeof n!=`object`||!(`version`in n)||n.version!==1||!(`iv`in n)||typeof n.iv!=`string`||!(`tag`in n)||typeof n.tag!=`string`||!(`ciphertext`in n)||typeof n.ciphertext!=`string`)throw Error(`Invalid encrypted OAuth credential format.`);let r=Buffer.from(n.iv,`base64`),i=Buffer.from(n.tag,`base64`);if(r.length!==12||i.length!==16)throw Error(`Invalid OAuth credential nonce or tag.`);let a=s(`aes-256-gcm`,t,r);a.setAuthTag(i);let o=JSON.parse(Buffer.concat([a.update(Buffer.from(n.ciphertext,`base64`)),a.final()]).toString(`utf8`));if(!o||typeof o!=`object`||Array.isArray(o))throw Error(`Invalid OAuth credential entry.`);return o}var yt=class{baseDir;fallback=new bt;unavailable=!1;constructor(e=ht()){this.baseDir=e}get isDegraded(){return this.unavailable}async withLock(e,t,n){return mt(this,e,async()=>{if(this.unavailable)return t();await this.key();let r=await re(this.pathFor(e),{realpath:!1,retries:{retries:100,minTimeout:50,maxTimeout:100,factor:1},stale:3e4});try{return n?.throwIfAborted(),await t()}finally{await r()}},n)}pathFor(e){return i(this.baseDir,`${gt(e)}.json`)}async key(){await g(this.baseDir,{recursive:!0,mode:448});let e=await h(this.baseDir);if(!e.isDirectory()||e.uid!==process.getuid?.())throw Error(`OAuth credential directory is not owned by this user.`);await m(this.baseDir,448);let t=i(this.baseDir,`key.bin`),n;try{n=await v(t,`wx`,384),await n.writeFile(l(32)),await n.close(),n=void 0}catch(e){if(n&&await n.close(),e.code!==`EEXIST`)throw e}let r=await h(t);if(!r.isFile()||r.isSymbolicLink()||r.uid!==process.getuid?.()||r.mode&63)throw Error(`OAuth encryption key is not an owner-only regular file.`);let a=await y(t);if(a.length!==32)throw Error(`Invalid OAuth encryption key.`);let o=await h(t);if(o.ino!==r.ino||o.mode&63)throw Error(`OAuth encryption key changed during read.`);return a}async read(e){let t=await this.fallback.read(e);if(t)return t;if(!this.unavailable)try{let t=await this.key(),n=this.pathFor(e),r=await h(n);if(!r.isFile()||r.isSymbolicLink()||r.uid!==process.getuid?.()||r.mode&63)throw Error(`OAuth credential file is not owner-only.`);let i=await y(n,`utf8`),a=await h(n);return a.ino!==r.ino||a.mode&63?void 0:vt(i,t)}catch{return}}async write(e,t){if(this.unavailable)await this.fallback.write(e,t);else try{let n=await this.key(),r=this.pathFor(e),a=i(this.baseDir,`.${gt(e)}-${l(12).toString(`hex`)}.tmp`),o=await v(a,`wx`,384);try{await o.writeFile(JSON.stringify(_t(t,n)))}catch(e){throw await o.close(),await S(a,{force:!0}),e}await o.close();try{await x(a,r)}catch(e){throw await S(a,{force:!0}),e}await this.fallback.clear(e)}catch{console.warn(`[oauth] Secure credential storage is unavailable; credentials are memory-only for this process.`),this.unavailable=!0,await this.fallback.write(e,t)}}async clear(e){await this.fallback.clear(e),await S(this.pathFor(e),{force:!0})}},bt=class{isEphemeral=!0;entries=/* @__PURE__ */ new Map;async read(e){return this.entries.get(e)}async write(e,t){this.entries.set(e,t)}async clear(e){this.entries.delete(e)}};async function xt(e,t,n){let r=await e.read(t);if(r&&r.serverUrl===n)return r}function St(e){return e?.access_token}function I(e,t){return e.replace(/\/$/,``)===t.replace(/\/$/,``)}var Ct=class{serverName;serverUrl;store;callbackServer;config;logger;callbackPort;callbackTimeoutMs;onAuthorizationUrl;pendingState;authorizationCancelled=!1;pendingCallback;flowCodeVerifier;flowClientInformation;flowDiscoveryState;flowTokenFingerprint;tokenGeneration;tokenFingerprint;interactiveGrant=!1;constructor(e){this.serverName=e.serverName,this.serverUrl=e.serverUrl,this.store=e.store,this.callbackServer=e.callbackServer,this.config=e.config??{},this.logger=e.logger,this.callbackPort=e.callbackPort??19876,this.callbackTimeoutMs=e.callbackTimeoutMs,this.onAuthorizationUrl=e.onAuthorizationUrl}async prepareCallback(){this.callbackPort===0&&await this.callbackServer.listen(0)}get redirectUrl(){return this.config.grantType===`client_credentials`?void 0:this.config.redirectUri?this.config.redirectUri:this.callbackServer.redirectUri?.()||`http://127.0.0.1:${this.callbackPort>0?this.callbackPort:this.callbackServer.getPort()??19876}${Qe}`}get clientMetadata(){let e=this.config.grantType===`client_credentials`,t=e?[]:[this.redirectUrl];return{client_name:this.config.clientName??`mcp-proxy`,...this.config.clientUri?{client_uri:this.config.clientUri}:{},redirect_uris:t,grant_types:e?[`client_credentials`]:[`authorization_code`,`refresh_token`],response_types:e?[]:[`code`],token_endpoint_auth_method:this.config.clientSecret?`client_secret_post`:`none`,...this.config.scope?{scope:this.config.scope}:{}}}state(){return this.pendingState=l(32).toString(`hex`),this.pendingState}async clientInformation(e){if(this.config.clientId)return{client_id:this.config.clientId,...this.config.clientSecret?{client_secret:this.config.clientSecret}:{},...e?{issuer:e.issuer}:{}};if(this.flowClientInformation&&(!e||!this.flowClientInformation.issuer||I(this.flowClientInformation.issuer,e.issuer)))return this.flowClientInformation;let t=await this.readBoundEntry(),n=t?.tokens?.refresh_token&&!this.interactiveGrant||this.registrationMatchesRedirect(t??{})?t?.clientInformation:void 0;return e&&n?.issuer&&!I(n.issuer,e.issuer)?void 0:n}async saveClientInformation(e,t){if(t&&e.issuer&&!I(e.issuer,t.issuer))throw Error(`OAuth client information issuer does not match the discovered issuer.`);this.flowClientInformation=e,await this.mergeEntry({clientInformation:e})}async tokens(e){let t=await this.readBoundEntry(),n=t?.tokens;return this.tokenGeneration=t?.generation,this.tokenFingerprint=St(n),e&&n?.issuer&&!I(n.issuer,e.issuer)?void 0:n}async saveTokens(e,t){if(t&&e.issuer&&!I(e.issuer,t.issuer))throw Error(`OAuth token issuer does not match the discovered issuer.`);this.flowCodeVerifier=void 0;let n=await this.readBoundEntry();if(n?.generation!==this.tokenGeneration||n?.tokens?.access_token!==this.tokenFingerprint)return;let r=e.expires_in;await this.mergeEntry({tokens:e,generation:(n?.generation??0)+1,expiresAt:typeof r==`number`&&Number.isFinite(r)&&r>0?Date.now()+r*1e3:void 0,codeVerifier:void 0}),this.tokenGeneration=(n?.generation??0)+1,this.tokenFingerprint=e.access_token,this.interactiveGrant=!1}async saveDiscoveryState(e){this.flowDiscoveryState=e,await this.mergeEntry({discoveryState:e})}async discoveryState(){return this.flowDiscoveryState??(await this.readBoundEntry())?.discoveryState}async saveCodeVerifier(e){this.flowCodeVerifier=e,await this.mergeEntry({codeVerifier:e})}async codeVerifier(){if(this.flowCodeVerifier)return this.flowCodeVerifier;let e=await this.readBoundEntry();if(!e?.codeVerifier)throw Error(`No PKCE code verifier stored for MCP server "${this.serverName}"; restart the authorization.`);return e.codeVerifier}async redirectToAuthorization(e){this.assertAuthorizationActive();let t=this.pendingState;if(!t)throw Error(`No authorization state was reserved for MCP server "${this.serverName}".`);try{if(this.flowTokenFingerprint=this.tokenFingerprint,this.assertAuthorizationActive(),await this.callbackServer.listen(this.callbackPort),this.assertAuthorizationActive(),await this.callbackServer.reserve(t,this.callbackTimeoutMs),this.authorizationCancelled&&this.callbackServer.cancel(t),this.assertAuthorizationActive(),this.pendingCallback=this.callbackServer.waitForCallback(t,this.callbackTimeoutMs),this.pendingCallback.catch(()=>void 0),this.onAuthorizationUrl){await this.onAuthorizationUrl(e,this.serverName),this.assertAuthorizationActive();return}this.logger?.info(`[oauth] Authorize MCP server "${this.serverName}" by visiting: ${e.toString()}`)}catch(e){throw this.cancelAuthorization(),e}}cancelAuthorization(){this.authorizationCancelled=!0,this.pendingState&&this.callbackServer.cancel(this.pendingState),this.pendingCallback=void 0,this.pendingState=void 0}assertAuthorizationActive(){if(this.authorizationCancelled)throw Error(`Authorization cancelled.`)}async waitForAuthorizationCode(){return(await this.waitForAuthorizationCallback()).get(`code`)}async waitForAuthorizationCallback(){let e=this.pendingCallback,t=this.pendingState;if(!e)throw Error(`No authorization is in progress for MCP server "${this.serverName}".`);let n=this.watchForPeerAuthorization();try{let r=await Promise.race([e,n.result]);if(r.state!==t)throw Error(`OAuth callback state mismatch.`);let i=new URLSearchParams({code:r.code,state:r.state});return r.iss!==void 0&&i.set(`iss`,r.iss),i}catch(e){throw t&&this.callbackServer.cancel(t),e}finally{n.stop(),this.pendingCallback=void 0,this.pendingState=void 0}}watchForPeerAuthorization(){let e,t=!1,n=()=>{t=!0,e&&clearTimeout(e)},r=new Promise((n,r)=>{let i=this.flowTokenFingerprint,a=async()=>{if(t)return;let e=St((await this.readBoundEntry().catch(()=>void 0))?.tokens);e!==void 0&&e!==i?r(/* @__PURE__ */ Error(`MCP server "${this.serverName}" was authorized by another session; reconnect to use the shared credentials.`)):o()},o=()=>{t||(e=setTimeout(()=>void a(),1e3),e.unref?.())};o()});return r.catch(()=>void 0),{result:r,stop:n}}hasPendingAuthorization(){return this.pendingCallback!==void 0}prepareTokenRequest(e){if(this.config.grantType!==`client_credentials`)return;let t=new URLSearchParams({grant_type:`client_credentials`}),n=e??this.config.scope;return n&&t.set(`scope`,n),t}async invalidateCredentials(e){if(e===`all`||e===`client`)this.flowClientInformation=void 0,this.flowCodeVerifier=void 0,this.flowDiscoveryState=void 0,await this.store.clear(this.serverName);else if(e===`tokens`){let e=await this.readBoundEntry();if(e?.generation!==this.tokenGeneration||e?.tokens?.access_token!==this.tokenFingerprint)return;await this.mergeEntry({tokens:void 0,expiresAt:void 0})}else e===`verifier`&&(this.flowCodeVerifier=void 0,await this.mergeEntry({codeVerifier:void 0})),e===`discovery`&&(this.flowDiscoveryState=void 0,await this.mergeEntry({discoveryState:void 0}))}async readBoundEntry(){let e=await this.store.read(this.serverName);if(e){if(e.serverUrl!==this.serverUrl)this.logger?.warn(`[oauth] Stored credentials for "${this.serverName}" were issued for a different URL and were ignored.`);else return e}}registrationMatchesRedirect(e){let t=e.clientInformation&&`redirect_uris`in e.clientInformation?e.clientInformation.redirect_uris:void 0;if(!Array.isArray(t)||t.length===0)return!0;let n=this.redirectUrl;return n===void 0||t.includes(n)}async mergeEntry(e){let t=await this.readBoundEntry()??{};await this.store.write(this.serverName,{...t,...e,serverUrl:this.serverUrl,updatedAt:Date.now()})}readCredential(){return this.readBoundEntry()}prepareInteractiveGrant(){this.interactiveGrant=!0,this.flowClientInformation=void 0}withCredentialLock(e,t){return pt(this.store,this.serverName,e,t)}};let wt;function Tt(e){return typeof e.auth==`object`&&e.auth?.type===`api-key`?`api-key`:e.auth===!1||e.oauth===!1?e.bearerToken||e.bearerTokenEnv?`bearer`:`none`:e.auth===`bearer`||e.bearerToken||e.bearerTokenEnv?`bearer`:e.auth===`oauth`?`oauth`:Object.keys(e.headers??{}).some(e=>Et.test(e))?`none`:`oauth`}const Et=/authorization|api[-_]?key|token|secret|cookie/i;function Dt(e){return e.bearerTokenEnv?process.env[e.bearerTokenEnv]:e.bearerToken}function Ot(e){if(Tt(e.config)!==`oauth`)return;let t=e.config.oauth===!1?void 0:e.config.oauth;return new Ct({serverName:e.serverName,serverUrl:e.config.url,store:e.store??new yt,callbackServer:e.callbackServer??(e.store?.isEphemeral?wt??=new st({rendezvous:!1}):ct()),config:t,logger:e.logger,callbackPort:e.store?.isEphemeral&&!t?.redirectUri?0:kt(e.config,e.workspaceRoot),callbackTimeoutMs:e.callbackTimeoutMs,onAuthorizationUrl:e.onAuthorizationUrl})}function kt(e,t=j()){let n=e.oauth===!1?void 0:e.oauth;if(n?.redirectUri){let e=Number.parseInt(new URL(n.redirectUri).port,10);return Number.isFinite(e)&&e>0?e:Ze(t)}return Ze(t)}function L(e,t=process.env){return e.replace(/\$\{([^}]+)\}/g,(e,n)=>{let r=t[n];return r===void 0?`\${${n}}`:r})}function R(e,t){if(typeof e==`string`)return L(e,t);if(Array.isArray(e))return e.map(e=>R(e,t));if(typeof e==`object`&&e){let n={};for(let[r,i]of Object.entries(e))n[r]=R(i,t);return n}return e}const At=[/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\./,/^224\./,/^240\./,/^localhost$/i,/^.*\.localhost$/i,/^\[::\]/,/^\[::1\]/,/^\[0:0:0:0:0:0:0:1\]/,/^\[0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:1\]/i,/^\[fe80:/i,/^\[fc00:/i,/^\[fd00:/i,/^\[::ffff:127\./i,/^\[::ffff:7f[0-9a-f]{2}:/i,/^\[::ffff:10\./i,/^\[::ffff:a[0-9a-f]{2}:/i,/^\[::ffff:172\.(1[6-9]|2\d|3[01])\./i,/^\[::ffff:ac1[0-9a-f]:/i,/^\[::ffff:192\.168\./i,/^\[::ffff:c0a8:/i,/^\[::ffff:169\.254\./i,/^\[::ffff:a9fe:/i,/^\[::ffff:0\./i,/^\[::127\./i,/^\[::7f[0-9a-f]{2}:/i,/^\[::10\./i,/^\[::a[0-9a-f]{2}:/i,/^\[::192\.168\./i,/^\[::c0a8:/i];function jt(e,t){let n=t?.allowPrivateIPs??!1,r=t?.enforceHttps??!0,i;try{i=new URL(e)}catch{throw Error(`Invalid URL format: ${e}`)}let a=i.protocol.replace(`:`,``);if(r&&a!==`https`)throw Error(`HTTPS is required for security. URL uses '${a}://'. Set security.enforceHttps: false to allow HTTP.`);if(a!==`http`&&a!==`https`)throw Error(`Invalid URL protocol '${a}://'. Only http:// and https:// are allowed.`);if(!n){let e=i.hostname.toLowerCase();if(At.some(t=>t.test(e)))throw Error(`Private IP addresses and localhost are blocked for security (${e}). Set security.allowPrivateIPs: true to allow internal networks.`)}}function Mt(e,t=process.env){let n=L(e.url,t);if(jt(n,e.security),e.validation){if(e.validation.url&&!new RegExp(e.validation.url).test(n))throw Error(`Remote config URL "${n}" does not match validation pattern: ${e.validation.url}`);if(e.validation.headers&&Object.keys(e.validation.headers).length>0){if(!e.headers){let t=Object.keys(e.validation.headers);throw Error(`Remote config is missing required headers: ${t.join(`, `)}`)}for(let[n,r]of Object.entries(e.validation.headers)){if(!(n in e.headers))throw Error(`Remote config is missing required header: ${n}`);let i=L(e.headers[n],t);if(!new RegExp(r).test(i))throw Error(`Remote config header "${n}" value "${i}" does not match validation pattern: ${r}`)}}}}const Nt=O.object({name:O.string(),description:O.string(),folder:O.string().optional()}),Pt=O.object({skill:Nt.optional()}),Ft=O.object({instruction:O.string().optional(),toolBlacklist:O.array(O.string()).optional(),omitToolDescription:O.boolean().optional(),prompts:O.record(O.string(),Pt).optional()}).optional(),It=O.object({command:O.string(),args:O.array(O.string()).optional(),env:O.record(O.string(),O.string()).optional(),cwd:O.string().optional(),disabled:O.boolean().optional(),instruction:O.string().optional(),timeout:O.number().positive().optional(),requestTimeout:O.number().positive().optional(),config:Ft}),Lt=O.union([O.literal(!1),O.object({grantType:O.enum([`authorization_code`,`client_credentials`]).optional(),clientId:O.string().optional(),clientSecret:O.string().optional(),scope:O.string().optional(),redirectUri:O.string().optional(),clientName:O.string().optional(),clientUri:O.string().optional()})]).optional(),Rt=O.discriminatedUnion(`mode`,[O.strictObject({type:O.literal(`api-key`),mode:O.literal(`bearer`)}),O.strictObject({type:O.literal(`api-key`),mode:O.literal(`header`),name:O.string().regex(/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/).max(128)})]),zt={auth:O.union([O.literal(`oauth`),O.literal(`bearer`),O.literal(!1),Rt]).optional(),bearerToken:O.string().optional(),bearerTokenEnv:O.string().optional(),oauth:Lt},Bt=O.object({...zt,url:O.string().url(),headers:O.record(O.string(),O.string()).optional(),type:O.enum([`http`,`sse`]).optional(),disabled:O.boolean().optional(),instruction:O.string().optional(),timeout:O.number().positive().optional(),requestTimeout:O.number().positive().optional(),config:Ft}),Vt=O.union([It,Bt]),Ht=O.object({url:O.string().optional(),headers:O.record(O.string(),O.string()).optional()}).optional(),Ut=O.object({allowPrivateIPs:O.boolean().optional(),enforceHttps:O.boolean().optional()}).optional(),Wt=O.object({url:O.string(),headers:O.record(O.string(),O.string()).optional(),validation:Ht,security:Ut,mergeStrategy:O.enum([`local-priority`,`remote-priority`,`merge-deep`]).optional()}),Gt=O.object({paths:O.array(O.string())}),Kt=O.union([O.boolean(),O.object({maxBytes:O.number().int().positive().optional(),maxLines:O.number().int().positive().optional(),structuredMaxBytes:O.number().int().positive().optional()})]).optional(),qt=O.object({type:O.enum([`stdio`,`http`,`sse`,`stdio-http`]).optional(),port:O.number().int().positive().optional(),host:O.string().optional(),keepAlive:O.boolean().optional(),outputGuard:Kt}).optional(),Jt=O.object({id:O.string().optional(),proxy:qt,mcpServers:O.record(O.string(),Vt),remoteConfigs:O.array(Wt).optional(),skills:Gt.optional()}),Yt=O.object({command:O.string(),args:O.array(O.string()).optional(),env:O.record(O.string(),O.string()).optional(),cwd:O.string().optional()}),Xt=O.object({...zt,url:O.string().url(),headers:O.record(O.string(),O.string()).optional()}),Zt=O.object({...zt,url:O.string().url(),headers:O.record(O.string(),O.string()).optional()}),Qt=O.object({name:O.string(),description:O.string(),folder:O.string().optional()}),$t=O.object({skill:Qt.optional()}),en=O.discriminatedUnion(`transport`,[O.object({name:O.string(),instruction:O.string().optional(),toolBlacklist:O.array(O.string()).optional(),omitToolDescription:O.boolean().optional(),prompts:O.record(O.string(),$t).optional(),timeout:O.number().positive().optional(),requestTimeout:O.number().positive().optional(),transport:O.literal(`stdio`),config:Yt}),O.object({name:O.string(),instruction:O.string().optional(),toolBlacklist:O.array(O.string()).optional(),omitToolDescription:O.boolean().optional(),prompts:O.record(O.string(),$t).optional(),timeout:O.number().positive().optional(),requestTimeout:O.number().positive().optional(),transport:O.literal(`http`),config:Xt}),O.object({name:O.string(),instruction:O.string().optional(),toolBlacklist:O.array(O.string()).optional(),omitToolDescription:O.boolean().optional(),prompts:O.record(O.string(),$t).optional(),timeout:O.number().positive().optional(),requestTimeout:O.number().positive().optional(),transport:O.literal(`sse`),config:Zt})]),tn=O.object({id:O.string().optional(),proxy:qt,mcpServers:O.record(O.string(),en),skills:Gt.optional()});function nn(e,t=process.env){let n={};for(let[r,i]of Object.entries(e.mcpServers))if(!(`disabled`in i&&i.disabled===!0)){if(`command`in i){let e=i,a=L(e.command,t),o=e.args?.map(e=>L(e,t)),s=e.env?R(e.env,t):void 0,c=e.cwd?L(e.cwd,t):void 0;n[r]={name:r,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:`stdio`,config:{command:a,args:o,env:s,cwd:c}}}else if(`url`in i){let e=i,a=e.type===`sse`?`sse`:`http`,o=L(e.url,t),s=e.headers?R(e.headers,t):void 0;n[r]={name:r,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:a,config:{url:o,headers:s,...e.auth===void 0?{}:{auth:e.auth},...e.bearerToken?{bearerToken:L(e.bearerToken,t)}:{},...e.bearerTokenEnv?{bearerTokenEnv:e.bearerTokenEnv}:{},...e.oauth===void 0?{}:{oauth:e.oauth}}}}}return{id:e.id,proxy:e.proxy,mcpServers:n,skills:e.skills}}function rn(e,t=process.env){let n=nn(Jt.parse(e),t);return tn.parse(n)}var an=class{cacheDir;cacheTTL;readEnabled;writeEnabled;logger;constructor(e,t=console){this.cacheDir=i(ne(),`mcp-proxy-cache`,`remote-configs`),this.cacheTTL=e?.ttl||36e5,this.readEnabled=e?.readEnabled===void 0||e.readEnabled,this.writeEnabled=e?.writeEnabled===void 0||e.writeEnabled,this.logger=t}generateCacheKey(e){return c(`sha256`).update(e).digest(`hex`)}getCacheFilePath(e){return i(this.cacheDir,`${e}.json`)}async ensureCacheDir(){try{await g(this.cacheDir,{recursive:!0})}catch(e){if(e?.code!==`EEXIST`)throw e}}async get(t){if(!this.readEnabled)return null;try{await this.ensureCacheDir();let n=this.generateCacheKey(t),r=this.getCacheFilePath(n);if(!e(r))return null;let i=await y(r,`utf-8`),a=JSON.parse(i),o=Date.now();if(o>a.expiresAt)return await w(r).catch(()=>{}),null;let s=Math.round((a.expiresAt-o)/1e3);return this.logger.debug(`Remote config cache hit for ${t} (expires in ${s}s)`),a.data}catch(e){return this.logger.warn(`Failed to read remote config cache for ${t}`,e),null}}async set(e,t){if(this.writeEnabled)try{await this.ensureCacheDir();let n=this.generateCacheKey(e),r=this.getCacheFilePath(n),i=Date.now(),a={data:t,timestamp:i,expiresAt:i+this.cacheTTL,url:e};await T(r,JSON.stringify(a,null,2),`utf-8`),this.logger.debug(`Cached remote config for ${e} (TTL: ${Math.round(this.cacheTTL/1e3)}s)`)}catch(t){this.logger.warn(`Failed to write remote config cache for ${e}`,t)}}async clear(t){try{let n=this.generateCacheKey(t),r=this.getCacheFilePath(n);e(r)&&(await w(r),this.logger.info(`Cleared remote config cache for ${t}`))}catch(e){this.logger.warn(`Failed to clear remote config cache for ${t}`,e)}}async clearAll(){try{if(!e(this.cacheDir))return;let t=await b(this.cacheDir),n=t.filter(e=>e.endsWith(`.json`)).map(e=>w(i(this.cacheDir,e)).catch(t=>{this.logger.debug(`Failed to delete remote config cache file ${e}`,t)}));await Promise.all(n),this.logger.info(`Cleared all remote config cache entries (${t.length} files)`)}catch(e){this.logger.warn(`Failed to clear all remote config cache`,e)}}async cleanExpired(){try{if(!e(this.cacheDir))return;let t=Date.now(),n=(await b(this.cacheDir)).filter(e=>e.endsWith(`.json`)),r=(await Promise.all(n.map(async e=>{let n=i(this.cacheDir,e);try{let e=await y(n,`utf-8`),r=JSON.parse(e);return t>r.expiresAt&&(await w(n),!0)}catch(e){return await w(n).catch(()=>{this.logger.debug(`Failed to delete corrupt cache file ${n}`,e)}),this.logger.warn(`Removed unreadable remote config cache file ${n}`,e),!0}}))).filter(Boolean).length;r>0&&this.logger.info(`Cleaned up ${r} expired remote config cache entries`)}catch(e){this.logger.warn(`Failed to clean expired remote config cache`,e)}}async getStats(){try{if(!e(this.cacheDir))return{totalEntries:0,totalSize:0};let t=(await b(this.cacheDir)).filter(e=>e.endsWith(`.json`)),n=(await Promise.all(t.map(async e=>{let t=i(this.cacheDir,e);try{let e=await y(t,`utf-8`);return Buffer.byteLength(e,`utf-8`)}catch{return 0}}))).reduce((e,t)=>e+t,0);return{totalEntries:t.length,totalSize:n}}catch(e){return this.logger.warn(`Failed to get remote config cache stats`,e),{totalEntries:0,totalSize:0}}}isReadEnabled(){return this.readEnabled}isWriteEnabled(){return this.writeEnabled}setReadEnabled(e){this.readEnabled=e}setWriteEnabled(e){this.writeEnabled=e}};function on(e,t){let n=e?.url,r=t?.url;return typeof n==`string`&&typeof r==`string`&&n!==r}function z(e,t){return e?t?{...e,...t}:e:t}function sn(e){return e.configSources?.length?e.configSources:e.configFilePath?[{path:e.configFilePath}]:[]}var cn=class{configSources;cacheTtlMs;cachedConfig=null;lastFetchTime=0;remoteConfigCache;logger;env;constructor(e,t=console){this.env=e.env??process.env,this.configSources=sn(e),this.cacheTtlMs=e.cacheTtlMs||6e4,this.logger=t;let n=e.useCache===void 0||e.useCache;if(this.remoteConfigCache=new an({ttl:e.remoteCacheTtlMs||36e5,readEnabled:n,writeEnabled:!0},t),this.configSources.length===0)throw Error(`configFilePath or configSources must be provided`)}async fetchConfiguration(e=!1){let t=Date.now();if(!e&&this.cachedConfig&&t-this.lastFetchTime<this.cacheTtlMs)return this.cachedConfig;let n=null,r=[],i=[];for(let e of this.configSources){let t=await this.loadRawConfigFromSource(e);if(t===null){i.push(e.path);continue}if((e.format??`claude`)===`claude`){let e=t;e.remoteConfigs&&r.push(...e.remoteConfigs)}let a=await this.parseConfig(t,e);n=n===null?a:this.mergeConfigurations(n,a,e.mergeStrategy??`remote-priority`)}if(n===null)throw Error(`Config file not found or empty: ${i.join(`, `)}`);let a=r.map(async e=>{try{return Mt(e,this.env),{config:await this.loadFromUrl(e),mergeStrategy:e.mergeStrategy||`local-priority`,url:e.url}}catch(t){return this.logger.warn(`Failed to fetch remote config from ${e.url}`,t),null}}),o=await Promise.all(a);for(let e of o)e!==null&&(n=this.mergeConfigurations(n,e.config,e.mergeStrategy));if(!n.mcpServers||typeof n.mcpServers!=`object`)throw Error(`Invalid MCP configuration: missing or invalid mcpServers`);return this.cachedConfig=n,this.lastFetchTime=t,n}async loadRawConfigFromSource(t){if(!e(t.path)){if(t.optional)return null;throw Error(`Config file not found: ${t.path}`)}try{let e=await y(t.path,`utf-8`);if(e.trim()===``)return null;if(t.path.endsWith(`.yaml`)||t.path.endsWith(`.yml`)){let t=D.loadAll(e);if(t.length>1)throw new D.YAMLException(`expected a single document in the stream, but found more`);return t[0]??null}return JSON.parse(e)??null}catch(e){throw e instanceof Error?Error(`Failed to load config file ${t.path}: ${e.message}`):Error(`Failed to load config file ${t.path}: Unknown error`)}}async parseConfig(e,t){try{if((t.format??`claude`)===`internal`)return tn.parse(e);let{remoteConfigs:n,...r}=e;return rn(r,this.env)}catch(e){throw e instanceof Error?Error(`Failed to parse config: ${e.message}`):Error(`Failed to parse config: Unknown error`)}}async loadFromUrl(e){try{let t=this.interpolateEnvVars(e.url),n=await this.remoteConfigCache.get(t);if(n)return n;let r=e.headers?Object.fromEntries(Object.entries(e.headers).map(([e,t])=>[e,this.interpolateEnvVars(t)])):{},i=await fetch(t,{headers:r,signal:AbortSignal.timeout(3e4)});if(!i.ok)throw Error(`Failed to fetch remote config: ${i.status} ${i.statusText}`);let a=rn(await i.json());return await this.remoteConfigCache.set(t,a),a}catch(t){throw t instanceof Error?Error(`Failed to fetch remote config from ${e.url}: ${t.message}`,{cause:t}):Error(`Failed to fetch remote config from ${e.url}: Unknown error`)}}interpolateEnvVars(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=this.env[t];return n===void 0?(this.logger.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}mergeConfigurations(e,t,n){switch(n){case`local-priority`:return{id:e.id??t.id,proxy:z(t.proxy,e.proxy),mcpServers:{...t.mcpServers,...e.mcpServers},skills:z(t.skills,e.skills)};case`remote-priority`:return{id:t.id??e.id,proxy:z(e.proxy,t.proxy),mcpServers:{...e.mcpServers,...t.mcpServers},skills:z(e.skills,t.skills)};case`merge-deep`:{let n={...t.mcpServers};for(let[t,r]of Object.entries(e.mcpServers))if(n[t]){let e=n[t],i={...e.config,...r.config},a=`env`in e.config?e.config.env:void 0,o=`env`in r.config?r.config.env:void 0;(a||o)&&(i.env={...a,...o});let s=`headers`in e.config?e.config.headers:void 0,c=`headers`in r.config?r.config.headers:void 0;(s||c)&&(i.headers=on(e.config,r.config)?{...c}:{...s,...c}),n[t]={...e,...r,config:i}}else n[t]=r;return{id:e.id??t.id,proxy:z(t.proxy,e.proxy),mcpServers:n,skills:z(t.skills,e.skills)}}default:throw Error(`Unknown merge strategy: ${String(n)}`)}}clearCache(){this.cachedConfig=null,this.lastFetchTime=0}isCacheValid(){let e=Date.now();return this.cachedConfig!==null&&e-this.lastFetchTime<this.cacheTtlMs}};const ln=`[capability-discovery]`;function un(e,t=[]){return[...t,e]}function dn(e){return e?Array.isArray(e)?e:[e]:[]}function fn(e){return e.map(e=>({path:e}))}function pn(){let t=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],r=process.env.PROJECT_PATH;if(r)for(let n of t){let t=a(r,n);if(e(t))return t}let o=process.cwd();for(let r=0;r<=3;r++){for(let n of t){let t=i(o,n);if(e(t))return t}let r=n(o);if(r===o)break;o=r}return null}function mn(e=6){let t=``,n=e;for(;n>0;){let e=l(n);for(let r=0;r<e.length&&n>0;r++){let i=e[r];i>247||(t+=`23456789abcdefghjkmnpqrstuvwxyz`[i%31],n--)}}return t}function hn(e){let t=e.trimStart();if(!t.startsWith(`---`))return{frontMatter:null,content:e};let n=t.indexOf(`
|
|
2
|
+
---`,3);if(n===-1)return{frontMatter:null,content:e};let r=t.slice(4,n).trim();if(!r)return{frontMatter:null,content:e};let i={},a=r.split(`
|
|
3
|
+
`),o=null,s=[],c=null,l=0,u=()=>{o&&s.length>0&&(c===`literal`?i[o]=s.join(`
|
|
4
|
+
`).trimEnd():c===`folded`?i[o]=s.join(` `).trim():i[o]=s.join(``).trim()),o=null,s=[],c=null,l=0};for(let e=0;e<a.length;e++){let t=a[e],n=t.trim(),r=t.indexOf(`:`);if(r!==-1&&!t.startsWith(` `)&&!t.startsWith(` `)){u();let n=t.slice(0,r).trim(),s=t.slice(r+1).trim();if(s===`|`||s===`|-`){if(o=n,c=`literal`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else if(s===`>`||s===`>-`){if(o=n,c=`folded`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else(s.startsWith(`"`)&&s.endsWith(`"`)||s.startsWith(`'`)&&s.endsWith(`'`))&&(s=s.slice(1,-1)),n&&s&&(i[n]=s)}else if(c&&o){let e=t.match(/^(\s*)/)?.[1].length||0;if(n===``)s.push(``);else if(e>=l){let e=t.slice(l);s.push(e)}else u()}}return u(),{frontMatter:i,content:t.slice(n+4).trimStart()}}function gn(e){return e!==null&&typeof e.name==`string`&&e.name.length>0&&typeof e.description==`string`&&e.description.length>0}function _n(e){let{frontMatter:t,content:n}=hn(e);return t&&gn(t)?{skill:{name:t.name,description:t.description},content:n}:null}function B(e){let t=e.indexOf(`__`);return t>0?{serverName:e.substring(0,t),actualToolName:e.substring(t+2)}:{actualToolName:e}}async function vn(e,t){try{await t()}catch(t){console.error(`[mcp-proxy] ${e} cleanup failed: ${t instanceof Error?t.message:String(t)}`)}}async function yn(){await Promise.all([vn(`Process registry`,async()=>new ce(process.env.PROCESS_REGISTRY_PATH).cleanupStaleProcesses()),vn(`Port registry`,async()=>new he(process.env.PORT_REGISTRY_PATH).cleanupStaleAllocations())])}function bn(e){return e.endsWith(`.yaml`)||e.endsWith(`.yml`)}function V(e){return e instanceof Error?e.message:String(e)}function xn(e){return(e instanceof fe||typeof e==`object`&&!!e&&`code`in e)&&e.code===de}function Sn(e){let t=a(e),n=t.length>=2&&t[1]===`:`&&(t[0]>=`A`&&t[0]<=`Z`||t[0]>=`a`&&t[0]<=`z`)?`${t[0].toLowerCase()}${t.slice(1)}`:t,r=``,i=!1;for(let e of n)e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`||e>=`0`&&e<=`9`||e===`.`||e===`_`||e===`-`?(r+=e,i=!1):i||=(r+=`_`,!0);let o=0,s=r.length;for(;o<s&&r[o]===`_`;)o+=1;for(;s>o&&r[s-1]===`_`;)--s;return r.slice(o,s)}function H(e){return{...e,failures:[...e.failures??[]],skills:(e.skills??[]).map(e=>({...e})),servers:Object.fromEntries(Object.entries(e.servers).map(([e,t])=>[e,{...t,tools:(t.tools??[]).map(e=>({...e})),resources:(t.resources??[]).map(e=>({...e})),prompts:(t.prompts??[]).map(e=>({...e,arguments:e.arguments?.map(e=>({...e}))})),promptSkills:(t.promptSkills??[]).map(e=>({...e,skill:{...e.skill}})),capabilityDiscovery:t.capabilityDiscovery?{resources:{...t.capabilityDiscovery.resources},prompts:{...t.capabilityDiscovery.prompts}}:void 0}]))}}var Cn=class extends Error{constructor(){super(`Definitions cache uses an incompatible format and must be refreshed`),this.name=`DefinitionsCacheVersionError`}},U=class e{clientManager;skillService;cacheData;liveDefinitionsPromise=null;mergedDefinitionsPromise=null;logger;constructor(t,n,r,i=console){this.clientManager=t,this.skillService=n,this.cacheData=r?.cacheData&&e.isCacheValid(r.cacheData,{})?r.cacheData:void 0,this.logger=i}static async readFromFile(e){let t=await y(e,`utf-8`),n=bn(e)?D.load(t):JSON.parse(t);if(!n||typeof n!=`object`)throw Error(`Definitions cache must be an object`);let r=n;if(r.version!==2)throw new Cn;if(!r.servers||typeof r.servers!=`object`||Array.isArray(r.servers))throw Error(`Definitions cache is missing required fields`);return{...r,failures:Array.isArray(r.failures)?r.failures:[],skills:Array.isArray(r.skills)?r.skills:[],servers:Object.fromEntries(Object.entries(r.servers).map(([e,t])=>[e,{...t,tools:Array.isArray(t.tools)?t.tools:[],resources:Array.isArray(t.resources)?t.resources:[],prompts:Array.isArray(t.prompts)?t.prompts:[],promptSkills:Array.isArray(t.promptSkills)?t.promptSkills:[]}]))}}static async inspectFile(t,n){try{let r=await e.readFromFile(t);return e.isCacheValid(r,n)?{state:`usable`,cachePath:t,cache:r}:{state:`invalid`,cachePath:t,reason:`metadata_mismatch`}}catch(e){return e.code===`ENOENT`?{state:`absent`,cachePath:t}:e instanceof Cn?{state:`invalid`,cachePath:t,reason:`incompatible_schema`}:{state:`invalid`,cachePath:t,reason:`unreadable`,error:V(e)}}}static async writeToFile(e,t){let r=bn(e)?D.dump(t,{noRefs:!0}):JSON.stringify(t,null,2);await g(n(e),{recursive:!0}),await T(e,r,`utf-8`)}static getDefaultCachePath(e){let t=Array.isArray(e)?e:[e];if(t.length===0)throw Error(`getDefaultCachePath requires at least one config path`);let n=Sn(t[0]);if(t.length===1)return i(E(),`.mcp-proxy`,`${n}.definitions-cache.json`);let r=c(`sha256`).update(t.map(e=>a(e)).join(`\0`)).digest(`hex`).slice(0,12);return i(E(),`.mcp-proxy`,`${n}.${r}.definitions-cache.json`)}static generateConfigHash(e){return c(`sha256`).update(JSON.stringify(e)).digest(`hex`)}static isCacheValid(e,t){return!(e.version!==2||t.configHash&&e.configHash!==t.configHash||t.oneMcpVersion&&e.oneMcpVersion!==t.oneMcpVersion)}static async clearFile(e){await S(e,{force:!0})}clearLiveCache(){this.liveDefinitionsPromise=null,this.mergedDefinitionsPromise=null}setCacheData(t){this.cacheData=t&&e.isCacheValid(t,{})?t:void 0,this.mergedDefinitionsPromise=null}async collectForCache(e){let t=await this.collectLiveDefinitions(e);return this.setCacheData(t),this.liveDefinitionsPromise=Promise.resolve(H(t)),H(t)}logCapabilitySummary(e,t){let n=Object.values(e.servers).map(e=>({serverName:e.serverName,tools:e.tools.length,resources:{state:e.capabilityDiscovery?.resources.state??`unknown`,count:e.resources.length,error:e.capabilityDiscovery?.resources.error},prompts:{state:e.capabilityDiscovery?.prompts.state??`unknown`,count:e.prompts.length,error:e.capabilityDiscovery?.prompts.error}})),r=n.some(e=>e.resources.state===`degraded`||e.prompts.state===`degraded`),i={source:t,servers:n,failures:e.failures,degraded:r||e.failures.length>0};i.degraded?this.logger.warn(`${ln} MCP server capability summary`,i):this.logger.info(`${ln} MCP server capability summary`,i)}async getDefinitions(){return this.mergedDefinitionsPromise||=(async()=>{let e=this.clientManager.getAllClients();if(!this.cacheData)return this.getLiveDefinitions();let t=e.map(e=>e.serverName).filter(e=>!this.cacheData?.servers[e]);if(t.length===0)return H(this.cacheData);let n=await this.getLiveDefinitions(),r=H(this.cacheData);for(let e of t){let t=n.servers[e];t&&(r.servers[e]=t)}let i=/* @__PURE__ */ new Map;for(let e of[...r.failures,...n.failures])i.set(e.serverName,e.error);return r.failures=Array.from(i.entries()).map(([e,t])=>({serverName:e,error:t})),r.skills.length===0&&n.skills.length>0&&(r.skills=n.skills.map(e=>({...e}))),r})(),this.mergedDefinitionsPromise}async getServerDefinitions(){let e=await this.getDefinitions(),t=this.clientManager.getKnownServerNames();return t.length===0?Object.values(e.servers):t.map(t=>e.servers[t]).filter(e=>e!==void 0)}async getServersForTool(e){return(await this.getServerDefinitions()).filter(t=>t.tools.some(t=>t.name===e)).map(e=>e.serverName)}async getToolSchema(e,t){return(await this.getDefinitions()).servers[e]?.tools.find(e=>e.name===t)?.inputSchema}async getServersForResource(e){return(await this.getServerDefinitions()).filter(t=>t.resources.some(t=>t.uri===e)).map(e=>e.serverName)}async getPromptSkillByName(e){let t=await this.getDefinitions();for(let[n,r]of Object.entries(t.servers))for(let t of r.promptSkills)if(t.skill.name===e)return{serverName:n,promptName:t.promptName,skill:t.skill,autoDetected:t.autoDetected}}async getCachedFileSkills(){return(await this.getDefinitions()).skills.map(e=>({...e}))}async getLiveDefinitions(){return this.liveDefinitionsPromise||=this.collectLiveDefinitions(),this.liveDefinitionsPromise}async collectLiveDefinitions(e){let t=this.clientManager.getAllClients().filter(t=>e?.serverNames===void 0||e.serverNames.includes(t.serverName)),n=[],r={},i=await Promise.all(t.map(async e=>{try{let t=await e.listTools(),n=e.getServerCapabilities?.(),r=await this.listResourcesSafe(e,n?n.resources!==void 0:void 0),i=await this.listPromptsSafe(e,n?n.prompts!==void 0:void 0),a=new Set(e.toolBlacklist||[]),o=t.filter(e=>!a.has(e.name)),s=await this.collectPromptSkillsForClient(e,i.items);return{serverName:e.serverName,serverInstruction:e.serverInstruction,omitToolDescription:e.omitToolDescription,toolBlacklist:e.toolBlacklist,tools:o.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,_meta:e._meta})),resources:r.items,prompts:i.items,promptSkills:s,capabilityDiscovery:{resources:{state:r.state,error:r.error},prompts:{state:i.state,error:i.error}}}}catch(t){return n.push({serverName:e.serverName,error:V(t)}),null}}));for(let e of i)e&&(r[e.serverName]=e);let a={version:2,oneMcpVersion:e?.oneMcpVersion,generatedAt:(/* @__PURE__ */ new Date()).toISOString(),configPath:e?.configPath,configHash:e?.configHash,serverId:e?.serverId,servers:r,skills:await this.collectFileSkills(),failures:n};return this.logCapabilitySummary(a,`live`),a}async collectFileSkills(){return this.skillService?(await this.skillService.getSkills()).map(e=>this.toCachedFileSkill(e)):[]}toCachedFileSkill(e){return{name:e.name,description:e.description,location:e.location,basePath:e.basePath}}async listPromptsSafe(e,t){if(t===!1)return{items:[],state:`unsupported`};try{return{state:`available`,items:(await e.listPrompts()).map(e=>({name:e.name,description:e.description,arguments:e.arguments?.map(e=>({...e}))}))}}catch(e){return xn(e)?{items:[],state:`unsupported`}:{items:[],state:`degraded`,error:V(e)}}}async listResourcesSafe(e,t){if(t===!1)return{items:[],state:`unsupported`};try{return{state:`available`,items:(await e.listResources()).map(e=>({uri:e.uri,name:e.name,description:e.description,mimeType:e.mimeType}))}}catch(e){return xn(e)?{items:[],state:`unsupported`}:{items:[],state:`degraded`,error:V(e)}}}async collectPromptSkillsForClient(e,t){let n=new Set(e.prompts?Object.keys(e.prompts):[]),r=[];if(e.prompts)for(let[t,n]of Object.entries(e.prompts))n.skill&&r.push({promptName:t,skill:{...n.skill}});let i=t.filter(e=>!n.has(e.name)).slice(0,50),a=await Promise.all(i.map(async t=>{try{let n=_n((await e.getPrompt(t.name)).messages?.map(e=>{let t=e.content;return typeof t==`string`?t:t&&typeof t==`object`&&`text`in t?String(t.text):``}).join(`
|
|
5
|
+
`)||``);return n?{promptName:t.name,skill:n.skill,autoDetected:!0}:null}catch(n){return this.logger.warn(`[skill-detection] Failed to fetch prompt '${t.name}' from ${e.serverName}: ${V(n)}`),null}}));for(let e of a)e&&r.push(e);return r}};function wn(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Tn(e){if(typeof e==`string`||typeof e==`number`||typeof e==`boolean`||Array.isArray(e)&&e.every(e=>typeof e==`string`)||Array.isArray(e)&&e.every(e=>typeof e==`number`)||Array.isArray(e)&&e.every(e=>typeof e==`boolean`))return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}}function En(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Tn(t)]))}function W(e){if(e!==void 0)return e instanceof Error?{exception:e}:wn(e)&&(`attributes`in e||`exception`in e||`context`in e)?e:wn(e)?{attributes:En(e)}:{attributes:{value:Tn(e)}}}function Dn(e){let t=e.logger;return{backend:e.backend,enabled:e.enabled,endpoint:e.endpoint,tracesEndpoint:e.tracesEndpoint,logsEndpoint:e.logsEndpoint,endpointSource:e.endpointSource,filePath:e.filePath,trace(e,n){t.trace(e,W(n))},debug(e,n){t.debug(e,W(n))},info(e,n){t.info(e,W(n))},warn(e,n){t.warn(e,W(n))},error(e,n){t.error(e,W(n))},getTraceContext(){return e.getTraceContext()},runInSpan:(t,n,r)=>e.runInSpan(t,n,r),flush:()=>e.flush(),shutdown:()=>e.shutdown()}}async function On(e={}){return Dn(await ge({env:e.env,workspaceRoot:e.workspaceRoot,packageName:e.packageName??`@agimon-ai/po-mcp-proxy`,serviceName:e.serviceName??`@agimon-ai/mcp-proxy`,serviceVersion:e.serviceVersion,logDir:e.logDir,logFileName:e.logFileName,maxFileSizeBytes:e.maxFileSizeBytes,maxFileCount:e.maxFileCount}))}var kn=class{provider;serverUrl;signal;sentToken;retryAfter=0;challenge={};constructor(e,t,n){this.provider=e,this.serverUrl=t,this.signal=n}async authorize(e={},t=this.signal){t?.throwIfAborted(),await this.provider.tokens();let n=e.fetchFn??this.challenge.fetchFn??fetch,r=await we(this.provider,{serverUrl:this.serverUrl,...this.challenge,...e,fetchFn:t?(e,r)=>n(e,{...r,signal:r?.signal?AbortSignal.any([t,r.signal]):t}):n});if(t?.throwIfAborted(),r!==`AUTHORIZED`)throw new k}async token(){let e=await this.provider.readCredential(),t=e?.tokens?.expires_in,n=typeof t==`number`&&Number.isFinite(t)&&t>0?Math.min(6e4,t*500):0;if(e?.tokens?.refresh_token&&e.expiresAt!==void 0&&Number.isFinite(e.expiresAt)&&Date.now()>=e.expiresAt-n&&Date.now()>=this.retryAfter&&!this.provider.hasPendingAuthorization())try{await this.provider.withCredentialLock(async()=>{let e=await this.provider.readCredential();e?.expiresAt!==void 0&&Date.now()>=e.expiresAt-n&&await this.authorize()},this.signal)}catch(e){if(e instanceof k||this.signal?.aborted)throw e;this.retryAfter=Date.now()+3e4}return this.sentToken=(await this.provider.tokens())?.access_token,this.sentToken}async onUnauthorized(e){let t=this.sentToken;this.challenge={...Ee(e.response),fetchFn:e.fetchFn},await this.provider.withCredentialLock(async()=>{let e=await this.provider.readCredential();if(!(e?.tokens?.access_token&&e.tokens.access_token!==t)){if(this.provider.hasPendingAuthorization())throw new k;await this.authorize()}},this.signal)}async recover(e,t,n){if(t?.throwIfAborted(),e instanceof ye&&await this.provider.withCredentialLock(async()=>{let n=await this.provider.tokens();this.provider.prepareInteractiveGrant(),this.challenge={...this.challenge,scope:Te(n?.scope,e.requiredScope),resourceMetadataUrl:e.resourceMetadataUrl,forceReauthorization:!0};try{await this.authorize({},t)}catch(e){if(!(e instanceof k)||!this.provider.hasPendingAuthorization())throw e}},t),!this.provider.hasPendingAuthorization())return;let r=()=>this.provider.cancelAuthorization();t?.addEventListener(`abort`,r,{once:!0});try{let e=await this.provider.waitForAuthorizationCallback();t?.throwIfAborted(),n?.(),await this.provider.withCredentialLock(async()=>{let n=await this.provider.discoveryState(),r=n?.authorizationServerMetadata;Oe({iss:e.get(`iss`)??void 0,expectedIssuer:r?.issuer??n?.authorizationServerUrl,issParameterSupported:r?.authorization_response_iss_parameter_supported===!0}),await this.authorize({authorizationCode:e.get(`code`)??void 0,iss:e.get(`iss`)??void 0,forceReauthorization:!1},t)},t)}finally{t?.removeEventListener(`abort`,r)}}};function An(e){let t=typeof e==`object`&&e?e:void 0;return{enabled:Kn(`MCP_OUTPUT_GUARD`)??e!==!1,maxBytes:t?.maxBytes,maxLines:t?.maxLines,structuredMaxBytes:t?.structuredMaxBytes}}var jn=class{enabled;maxBytes;maxLines;structuredMaxBytes;constructor(e={}){this.enabled=e.enabled??Kn(`MCP_OUTPUT_GUARD`)??!0,this.maxBytes=Gn(e.maxBytes)??51200,this.maxLines=Gn(e.maxLines)??2e3,this.structuredMaxBytes=Gn(e.structuredMaxBytes)??16384}isEnabled(){return this.enabled}async guard(e){if(!this.enabled)return e;let t=await this.guardContent(e);return await this.guardStructuredContent(t)}async guardContent(e){let t=Array.isArray(e.content)?e.content:[],n=t.filter(e=>e.type===`text`),r=t.filter(e=>e.type!==`text`),i=n.map(e=>typeof e.text==`string`?e.text:``).join(`
|
|
6
|
+
`),a=Un(i);if(a.bytes<=this.maxBytes&&a.lines<=this.maxLines)return e;let{path:o,error:s}=await Bn(`output`,i),c=Fn(a,o,s),l=Mn(this.maxBytes,this.maxLines,c),u=`${Nn(i,l.maxBytes,l.maxLines)}\n\n${c}`,d=Un(u),f=r.filter(e=>e.type===`image`).length,p={truncated:!0,originalBytes:a.bytes,returnedBytes:d.bytes,originalLines:a.lines,returnedLines:d.lines,...f>0?{imageBlocksPassedThrough:f}:{},...o?{fullOutputPath:o}:{},...s?{writeError:s}:{}};return{...e,content:[{type:`text`,text:u},...r],_meta:{...e._meta,"agiflowai/outputGuard":p}}}async guardStructuredContent(e){if(e.structuredContent===void 0)return e;let t=Hn(e.structuredContent),n=Wn(t);if(n<=this.structuredMaxBytes)return e;let{path:r,error:i}=await Bn(`structured-content`,t);return{...e,structuredContent:{omitted:!0,reason:`structuredContent exceeded the size limit and was replaced with this summary to keep the caller context bounded.`,rawBytes:n,summary:In(e.structuredContent),...r?{fullResultPath:r}:{},...i?{resultWriteError:i}:{}}}}};function Mn(e,t,n){let r=Un(`\n\n${n}`);return{maxBytes:Math.max(0,e-r.bytes),maxLines:Math.max(0,t-r.lines)}}function Nn(e,t,n){let r=e.split(`
|
|
7
|
+
`),i=[],a=0;for(let e of r){if(i.length>=n)break;let r=+(i.length>0),o=Wn(e);if(a+r+o>t){let n=t-a-r;n>0&&i.push(Pn(e,n));break}i.push(e),a+=r+o}return i.join(`
|
|
8
|
+
`)}function Pn(e,t){if(Wn(e)<=t)return e;let n=Buffer.from(e,`utf8`),r=Math.max(0,t);for(;r>0&&(n[r]&192)==128;)r--;return n.subarray(0,r).toString(`utf8`)}function Fn(e,t,n){let r=`[MCP tool output truncated: original ${e.lines.toLocaleString()} lines / ${qn(e.bytes)}.`;return t?`${r} Full text saved to: ${t}]`:`${r} Full output could not be saved: ${n??`unknown error`}]`}function In(e){let t=Vn(e);if(!t)return{type:e===null?`null`:typeof e,omitted:!0};let n=Object.keys(t);return{type:Array.isArray(e)?`array`:`object`,keyCount:Array.isArray(e)?e.length:n.length,keysPreview:n.slice(0,20).map(Ln),...Array.isArray(e)&&e.length>20?{itemsOmitted:e.length-20}:{},omitted:!0}}function Ln(e){return e.length<=120?e:`${e.slice(0,119)}…`}let Rn;function zn(){return Rn??=_(i(ne(),`mcp-proxy-output-`)),Rn}async function Bn(e,t){try{let n=await zn(),r=i(n,`${e}-${l(8).toString(`hex`)}.txt`);return await T(r,t,{encoding:`utf8`,mode:384}),{path:r}}catch(e){return Rn=void 0,{error:e instanceof Error?e.message:String(e)}}}function Vn(e){return typeof e==`object`&&e?e:void 0}function Hn(e){try{return JSON.stringify(e)??``}catch{return``}}function Un(e){return{bytes:Wn(e),lines:e.length===0?0:e.split(`
|
|
9
|
+
`).length}}function Wn(e){return Buffer.byteLength(e,`utf8`)}function Gn(e){if(typeof e!=`number`||!Number.isFinite(e))return;let t=Math.floor(e);return t>0?t:void 0}function Kn(e){let t=process.env[e]?.trim().toLowerCase();if(t){if([`0`,`false`,`no`,`off`].includes(t))return!1;if([`1`,`true`,`yes`,`on`].includes(t))return!0}}function qn(e){return e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(1)} KiB`:`${(e/1048576).toFixed(1)} MiB`}const G=`x-mcp-proxy-original-output-schema`;function Jn(e){return Array.from(e.slice(0,256)).filter(e=>{let t=e.charCodeAt(0);return t>=32&&t<=126||t>=160}).join(``)}var Yn=class extends ve{serverName;compatibility;calls;constructor(e,t,n,r){let i=new Ae,a=new je;super(e,{...t,jsonSchemaValidator:{getValidator:e=>t=>{let n=i.getStore()?.toolName,r=Object.hasOwn(e,G)?e[G]:e;try{!a.getValidator(r)(t).valid&&n&&this.warn(n,`tools/call`,`structuredContent`,`Structured output does not match its output schema.`)}catch{n&&this.warn(n,`tools/call`,`outputSchema`,`Output schema could not be compiled or evaluated.`)}return{valid:!0,data:t,errorMessage:void 0}}}}),this.serverName=n,this.compatibility=r,this.calls=i}warn(e,t,n,r){try{Promise.resolve(this.compatibility.onWarning({serverName:Jn(this.serverName),toolName:Jn(e),method:t,path:n,message:r})).catch(()=>{})}catch{}}request(e,t,n){if(t&&`~standard`in t)return super.request(e,t,n);if(e.method!==`tools/list`){let n=super.request(e,t);return e.method===`tools/call`?n.then(e=>{let t=this.calls.getStore();return t&&(t.result=e),e}):n}return super.request(e,{"~standard":{version:1,vendor:`mcp-proxy-output-compatibility`,validate:e=>this.validateListing(e)}},t)}validateListing(e){if(!e||typeof e!=`object`||!(`tools`in e)||!Array.isArray(e.tools))return{issues:[{message:`Invalid tools/list result`}]};let t=e.tools,n=t.map(e=>{if(!e||typeof e!=`object`)return e;let{outputSchema:t,...n}=e;return n}),r=this._wireCodec().validateResult(`tools/list`,{...e,tools:n});if(!r.ok)return{issues:[{message:`Invalid non-output tools/list descriptor`}]};for(let[e,n]of r.value.tools.entries()){let r=t[e];Object.hasOwn(r,`outputSchema`)&&(n.outputSchema={type:`object`,[G]:r.outputSchema},this._wireCodec().validateResult(`tools/list`,{tools:[r]}).ok||this.warn(n.name,`tools/list`,`tools/${e}/outputSchema`,`Output schema descriptor is not MCP-compatible.`))}return{value:r.value}}async listTools(e,t){let n=await super.listTools(e,t);return{...n,tools:n.tools.map(e=>e.outputSchema&&Object.hasOwn(e.outputSchema,G)?{...e,outputSchema:e.outputSchema[G]}:e)}}async callTool(e,t){let n={toolName:e.name,result:void 0};return this.calls.run(n,async()=>{try{return await super.callTool(e,t)}catch(t){if(!(t instanceof be)||t.code!==xe.InvalidRequest||t.message!==`Tool ${e.name} has an output schema but did not return structured content`||!n.result||n.result.structuredContent!==void 0||n.result.isError)throw t;return this.warn(e.name,`tools/call`,`structuredContent`,`Tool omitted structured output required by its output schema.`),n.result}})}};const Xn=`mcp-proxy-client-manager`,Zn=[0,100];function Qn(e){return e===`reconnecting`?`connecting`:e}var $n=class extends Error{serverName;attempts;code=`MCP_SERVER_RECOVERY_EXHAUSTED`;constructor(e,t,n){super(`MCP server "${e}" did not recover after ${t} attempts.`,n),this.serverName=e,this.attempts=t,this.name=`McpServerRecoveryExhaustedError`}};async function er(e){let t=await Promise.allSettled([Promise.resolve().then(()=>e.client.close()),Promise.resolve().then(()=>e.stdioTransport?.close())]);try{await e.processLease?.release({kill:!1,releasePort:!1})}catch(e){t.push({status:`rejected`,reason:e})}let n=t.flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(n.length)throw AggregateError(n,`MCP connection cleanup failed`)}function tr(e){return or(e).some(({message:e,code:t})=>{let n=e.toLowerCase(),r=ir(t);return n.includes(`unknown session`)||n.includes(`session not found`)||n.includes(`transport closed`)||n.includes(`connection closed`)||n.includes(`socket hang up`)||n.includes(`fetch failed`)||r===`econnreset`})}function nr(e){return e instanceof k||or(e).some(({message:e,code:t})=>{let n=e.toLowerCase();return t===`401`||n.includes(`unauthorized`)||n.includes(`http 401`)||n.includes(`invalid_token`)})}function rr(e){return or(e).some(({message:e,code:t})=>{let n=e.toLowerCase(),r=ir(t);return n.includes(`transport closed`)||n.includes(`connection closed`)||n.includes(`premature close`)||n.includes(`socket hang up`)||n.includes(`write epipe`)||n.includes(`read econnreset`)||n.includes(`fetch failed`)||r===`epipe`||r===`econnreset`})}function ir(e){return typeof e==`string`?e.toLowerCase():void 0}function ar(e){if(typeof e==`string`)return e;if(typeof e==`symbol`)return e.toString();if(typeof e==`object`&&e)try{return JSON.stringify(e)??`Unknown error`}catch{return`Unknown error`}return String(e)}function or(e){let t=/* @__PURE__ */ new Set,n=[],r=e;for(;r&&!t.has(r);)if(t.add(r),r instanceof Error){let e=r;n.push({message:r.message,code:e.code}),r=e.cause}else if(typeof r==`object`){let e=r;n.push({message:typeof e.message==`string`?e.message:ar(r),code:typeof e.code==`string`?e.code:void 0}),r=e.cause}else{n.push({message:ar(r)});break}return n}var sr=class{outputGuard;serverName;serverInstruction;toolBlacklist;omitToolDescription;prompts;transport;logger;client;stdioTransport;processLease;connected=!1;lifecycleState=`closed`;recoveryError;reconnectFn;reconnectPromise;recoverAuthorization;authorizationRecovery;pendingLeaseRelease;onDisconnected;onLifecycleChange;closing=!1;closePromise;lifetime=new AbortController;constructor(e,t,n,r,i,a){this.outputGuard=a,this.serverName=e,this.serverInstruction=i.instruction,this.toolBlacklist=i.toolBlacklist,this.omitToolDescription=i.omitToolDescription,this.prompts=i.prompts,this.transport=t,this.logger=r,this.client=n}setAuthorizationRecovery(e){this.recoverAuthorization=e}setStdioTransport(e){this.stdioTransport=e}setProcessLease(e){this.processLease=e}setConnected(e){this.connected=e,this.setLifecycleState(e?`connected`:`closed`),e&&(this.recoveryError=void 0)}getLifecycleState(){return this.lifecycleState}setLifecycleChangeCallback(e){this.onLifecycleChange=e}setLifecycleState(e,t){this.lifecycleState!==e&&(this.lifecycleState=e,this.onLifecycleChange?.(e,t))}async waitUntilReady(){await this.ensureReady()}getServerCapabilities(){return this.client.getServerCapabilities()}setReconnectFn(e){this.reconnectFn=e}setDisconnectedCallback(e){this.onDisconnected=e}handleStdioClosed(e){if(this.stdioTransport!==e||this.closing)return;let t=this.processLease;this.stdioTransport=void 0,this.processLease=void 0,this.connected=!1,this.recoveryError=void 0,this.setLifecycleState(`reconnecting`),this.pendingLeaseRelease=this.releaseProcessLease(t),!this.closing&&(this.logger.warn(`mcp_proxy.server.disconnected`,{"mcp.server.name":this.serverName,"mcp.server.transport":this.transport,"mcp.server.lifecycle":this.lifecycleState,"mcp.server.disconnect_reason":`stdio transport closed`,"mcp.server.recovery_mode":`proactive`}),this.onDisconnected?.(this),this.reconnectClient(`stdio transport closed`).catch(()=>{}))}async releaseProcessLease(e){try{await e?.release({kill:!1,releasePort:!1})}catch(e){this.logger.warn(`Failed to release process lease for ${this.serverName}`,e)}}async releaseOwnedResources(e){let t=this.stdioTransport,n=this.processLease,r=this.pendingLeaseRelease;this.stdioTransport=void 0,this.processLease=void 0,this.pendingLeaseRelease=void 0;try{t&&e.killChild&&await t.close()}finally{await Promise.all([r,n?.release({kill:!1,releasePort:!1})])}}async reconnectClient(e=`recoverable transport error`){if(this.lifetime.signal.throwIfAborted(),!this.reconnectFn)throw Error(`No reconnect function configured for ${this.serverName}`);let t=this.reconnectFn;this.reconnectPromise||=(async()=>{this.connected=!1,this.setLifecycleState(`reconnecting`),this.recoveryError=void 0,await this.releaseOwnedResources({killChild:!0});try{await this.client.close()}catch(e){this.logger.warn(`Failed to close stale client for ${this.serverName}`,e)}let n;for(let[r,i]of Zn.entries()){i>0&&await _e(i,void 0,{signal:this.lifetime.signal}),this.lifetime.signal.throwIfAborted();try{let n=await t(this.lifetime.signal);this.closing&&(await er(n),this.lifetime.signal.throwIfAborted()),this.client=n.client,this.recoverAuthorization=n.recoverAuthorization,n.stdioTransport&&(this.stdioTransport=n.stdioTransport),n.processLease&&(this.processLease=n.processLease),this.connected=!0,this.setLifecycleState(`connected`),this.logger.info(`mcp_proxy.server.recovered`,{"mcp.server.name":this.serverName,"mcp.server.transport":this.transport,"mcp.server.lifecycle":`connected`,"mcp.server.recovery_attempt":r+1,"mcp.server.recovery_trigger":e});return}catch(e){this.lifetime.signal.throwIfAborted(),n=e,this.logger.warn(`mcp_proxy.server.reconnect_failed`,{"mcp.server.name":this.serverName,"mcp.server.transport":this.transport,"mcp.server.recovery_attempt":r+1,"error.message":e instanceof Error?e.message:String(e)})}}throw this.connected=!1,this.recoveryError=new $n(this.serverName,Zn.length,{cause:n}),this.setLifecycleState(`degraded`,this.recoveryError.message),this.logger.error(`mcp_proxy.server.degraded`,{"mcp.server.name":this.serverName,"mcp.server.transport":this.transport,"mcp.server.lifecycle":`degraded`,"mcp.server.recovery_attempts":Zn.length,"error.message":n instanceof Error?n.message:String(n)}),this.recoveryError})();let n=this.reconnectPromise;try{await n}finally{this.reconnectPromise===n&&(this.reconnectPromise=void 0)}}async ensureReady(){if(this.lifetime.signal.throwIfAborted(),!this.connected){if(this.recoveryError)throw this.recoveryError;await this.reconnectClient(`operation requested while disconnected`)}}async withSessionRetry(e,t){t?.throwIfAborted(),await this.ensureReady(),t?.throwIfAborted();try{return await e()}catch(n){if(t?.throwIfAborted(),(n instanceof k||n instanceof ye)&&this.recoverAuthorization)return this.authorizationRecovery??=this.recoverAuthorization(n,t?AbortSignal.any([t,this.lifetime.signal]):this.lifetime.signal).then(()=>this.reconnectClient(`authorization recovered`)).finally(()=>{this.authorizationRecovery=void 0}),await this.authorizationRecovery,t?.throwIfAborted(),e();if(!this.reconnectFn||!tr(n)&&!rr(n))throw n;return this.logger.warn(`Session error for ${this.serverName}, reconnecting: ${n instanceof Error?n.message:String(n)}`),await this.reconnectClient(n instanceof Error?n.message:String(n)),t?.throwIfAborted(),await e()}}async listTools(){return this.withSessionRetry(async()=>(await this.client.listTools()).tools)}async listResources(){return this.withSessionRetry(async()=>(await this.client.listResources()).resources)}async listPrompts(){return this.withSessionRetry(async()=>(await this.client.listPrompts()).prompts)}async callTool(e,t,n){let r=n?.signal?AbortSignal.any([n.signal,this.lifetime.signal]):this.lifetime.signal,i=await this.withSessionRetry(async()=>{let i={signal:r,...n?.timeout===void 0?{}:{timeout:n.timeout}},a=await this.client.callTool({name:e,arguments:t},i);if(!De(a))throw Error(`Unexpected interactive response from MCP tool '${e}': this call requires a context-aware relay`);return a},r);if(r.throwIfAborted(),n?.onResult)try{await n.onResult(structuredClone(i))}catch(t){this.logger.warn(`MCP result observer failed for ${this.serverName}.${e}`,t)}return r.throwIfAborted(),this.outputGuard?await this.outputGuard.guard(i):i}async readResource(e,t){let n=t?.signal?AbortSignal.any([t.signal,this.lifetime.signal]):this.lifetime.signal,r=await this.withSessionRetry(async()=>await this.client.readResource({uri:e},{signal:n,...t?.timeout===void 0?{}:{timeout:t.timeout}}),n);return n.throwIfAborted(),r}async getPrompt(e,t){return this.withSessionRetry(async()=>await this.client.getPrompt({name:e,arguments:t}))}close(){return this.closePromise||=(this.closing=!0,this.lifetime.abort(/* @__PURE__ */ Error(`MCP client '${this.serverName}' is closed`)),this.connected=!1,this.setLifecycleState(`closed`),(async()=>{let e=(await Promise.allSettled([this.releaseOwnedResources({killChild:!0}),Promise.resolve().then(()=>this.client.close())])).flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(e.length)throw AggregateError(e,`Failed to close MCP client '${this.serverName}'`)})()),this.closePromise}},cr=class{outputSchemaValidation;clientCapabilities;clients=/* @__PURE__ */ new Map;serverConfigs=/* @__PURE__ */ new Map;connectionPromises=/* @__PURE__ */ new Map;connectionControllers=/* @__PURE__ */ new Map;disposed=!1;disposePromise;logger;repositoryPath;workspaceRoot;executionCwd;env;processOwnerId=u();outputGuard;stateListeners=/* @__PURE__ */ new Set;serverStates=/* @__PURE__ */ new Map;tokenStore;serverTokenStores=/* @__PURE__ */ new Map;serverRemovals=/* @__PURE__ */ new Map;onAuthorizationUrl;callbackTimeoutMs;callbackServer;resolveUrlCredentials;constructor(e=console,t=process.cwd(),n=new jn,r={},i,a,o,s,c={}){this.outputSchemaValidation=s,this.clientCapabilities=c,this.logger=e,this.repositoryPath=t,this.workspaceRoot=i,this.executionCwd=o,this.env=a,this.outputGuard=n,this.tokenStore=r.tokenStore,this.onAuthorizationUrl=r.onAuthorizationUrl,this.callbackTimeoutMs=r.callbackTimeoutMs,this.callbackServer=r.callbackServer,this.resolveUrlCredentials=r.resolveUrlCredentials}onServerStateChange(e){this.stateListeners.add(e);for(let[t,n]of this.serverStates)this.notifyListener(e,{...n,serverName:t});return()=>{this.stateListeners.delete(e)}}getServerState(e){return this.serverStates.get(e)?.state}emitServerState(e){this.serverStates.set(e.serverName,e);for(let t of this.stateListeners)this.notifyListener(t,e)}notifyListener(e,t){try{e(t)}catch(e){this.logger.warn(`[mcp-proxy] Server state listener threw for ${t.serverName}: ${e instanceof Error?e.message:String(e)}`)}}setOutputGuard(e){this.outputGuard=e}async cleanupChildProcesses(){await this.disconnectAll()}async connectToServer(e,t,n){if(await this.serverRemovals.get(e),n?.signal?.throwIfAborted(),this.disposed)throw Error(`The MCP client manager is disposed`);n?.tokenStore&&this.serverTokenStores.set(e,n.tokenStore),this.serverConfigs.set(e,t);let r=()=>{this.removeServer(e).catch(()=>this.logger.warn(`Failed to remove cancelled MCP server '${e}'.`))};n?.signal?.addEventListener(`abort`,r,{once:!0});try{await this.ensureConnected(e),n?.signal?.throwIfAborted()}finally{n?.signal?.removeEventListener(`abort`,r)}}async removeServer(e){let t=this.serverRemovals.get(e);if(t)return t;let n=this.serverTokenStores.get(e);this.serverConfigs.delete(e);let r=(async()=>{try{await this.disconnectServer(e)}finally{this.serverTokenStores.get(e)===n&&this.serverTokenStores.delete(e),await n?.clear(e),this.serverStates.delete(e)}})();this.serverRemovals.set(e,r);try{await r}finally{this.serverRemovals.get(e)===r&&this.serverRemovals.delete(e)}}registerServerConfigs(e){for(let[t,n]of Object.entries(e))this.serverConfigs.set(t,n)}getKnownServerNames(){return Array.from(this.serverConfigs.keys())}getServerRequestTimeout(e){return this.serverConfigs.get(e)?.requestTimeout}async ensureConnected(e){if(this.disposed)throw Error(`The MCP client manager is disposed`);let t=this.clients.get(e);if(t)return await t.waitUntilReady(),t;let n=this.connectionPromises.get(e);if(n)return await n;let r=this.serverConfigs.get(e);if(!r)throw Error(`No configuration found for server "${e}"`);let i=this.createConnection(e,r);this.connectionPromises.set(e,i);try{return await i}finally{this.connectionPromises.get(e)===i&&this.connectionPromises.delete(e)}}async createConnection(e,t){let n=t.timeout??3e4,r=new AbortController;this.connectionControllers.set(e,r),this.emitServerState({serverName:e,state:`connecting`});let i,a=new Promise((e,t)=>{i=()=>t(r.signal.reason),r.signal.addEventListener(`abort`,i,{once:!0}),r.signal.aborted&&i()}),o,s,c=new Promise((e,t)=>{s=e=>{clearTimeout(o),!(e||r.signal.aborted)&&(o=setTimeout(()=>{let e=/* @__PURE__ */ Error(`Connection timeout after ${n}ms`);r.abort(e),t(e)},n))},s(!1)}),l;try{l=await Promise.race([this.createSdkClientConnection(e,t,r.signal,e=>s?.(e)),c,a])}catch(n){let i=t.transport===`http`||t.transport===`sse`?t.config.auth:void 0,a=typeof i==`object`&&i?.type===`api-key`,o=n instanceof Error&&[`Invalid MCP API-key configuration.`,`MCP API-key credential is unavailable.`,`MCP credential destination was rejected.`].includes(n.message),s=a&&!o?/* @__PURE__ */ Error(`MCP API-key connection failed.`):n;throw this.emitServerState({serverName:e,state:this.disposed||r.signal.aborted&&!String(r.signal.reason).includes(`timeout`)?`closed`:nr(s)?`needs-auth`:`failed`,error:s instanceof Error?s.message:String(s)}),s}finally{s=void 0,clearTimeout(o),r.signal.removeEventListener(`abort`,i),this.connectionControllers.get(e)===r&&this.connectionControllers.delete(e)}let u=new sr(e,t.transport,l.client,this.logger,{instruction:t.instruction,toolBlacklist:t.toolBlacklist,omitToolDescription:t.omitToolDescription,prompts:t.prompts},this.outputGuard);u.setDisconnectedCallback(()=>void 0),u.setAuthorizationRecovery(l.recoverAuthorization),u.setLifecycleChangeCallback((t,n)=>{this.emitServerState({serverName:e,state:Qn(t),...n?{error:n}:{}})});try{if(l.stdioTransport&&u.setStdioTransport(l.stdioTransport),l.processLease&&u.setProcessLease(l.processLease),r.signal.throwIfAborted(),this.disposed)throw Error(`The MCP client manager is disposed`);if(u.setConnected(!0),u.setReconnectFn(async n=>{try{if(this.disposed)throw Error(`The MCP client manager is disposed`);return await this.createSdkClientConnection(e,t,n)}catch(t){throw this.logger.warn(`Failed to reconnect to ${e}`,t),t}}),!u.serverInstruction)try{let e=u.client.getInstructions();e&&(u.serverInstruction=e)}catch(t){this.logger.warn(`Failed to get server instruction from ${e}`,t)}return this.clients.set(e,u),u}catch(e){throw await u.close(),e}}createSdkClient(e,t=`auto`){let n={name:`@agimon-ai/po-mcp-proxy-client`,version:`0.1.0`},r={capabilities:structuredClone(this.clientCapabilities),versionNegotiation:t===`legacy`?{mode:`legacy`}:{mode:`auto`,probe:{timeoutMs:1e4,maxRetries:0}}};return this.outputSchemaValidation?new Yn(n,r,e,this.outputSchemaValidation):new ve(n,r)}async createSdkClientConnection(e,t,n,r){n?.throwIfAborted();let i;if(t.transport===`stdio`)i=await this.connectStdioSdkClient(e,this.createSdkClient(e),t.config,n);else if(t.transport===`http`||t.transport===`sse`)i=await this.connectUrlSdkClient(e,t.transport,t.config,!0,n,r);else{let{transport:e}=t;throw Error(`Unsupported transport type: ${e}`)}if(n?.aborted||this.disposed)throw await er(i),n?.throwIfAborted(),Error(`The MCP client manager is disposed`);return i}async connectUrlSdkClient(e,t,n,r=!0,i,a){i?.throwIfAborted();let o=n.auth,s=typeof o==`object`&&o?.type===`api-key`?o:void 0,c=this.resolveAuthHeaders(n),l;if(s){let r=new URL(n.url),a=s.mode===`bearer`?`Authorization`:s.name;if(s.mode!==`bearer`&&s.mode!==`header`||!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(a)||s.mode===`header`&&(a.toLowerCase()===`authorization`||/^(?:host|cookie|set-cookie|connection|keep-alive|te|trailer|upgrade|transfer-encoding|content-length|accept|origin|referer|forwarded|x-forwarded-.*|proxy-.*|sec-.*|mcp-session-id)$/i.test(a))||r.username||r.password||r.protocol!==`https:`&&!(r.protocol===`http:`&&[`localhost`,`127.0.0.1`,`[::1]`].includes(r.hostname))||n.bearerToken||n.bearerTokenEnv||n.oauth!==void 0||Object.keys(c??{}).some(e=>[`authorization`,a.toLowerCase()].includes(e.toLowerCase())))throw Error(`Invalid MCP API-key configuration.`);let o;try{o=await this.resolveUrlCredentials?.({serverName:e,transport:t,url:r.href,auth:s,signal:i})}catch{throw Error(`MCP API-key credential is unavailable.`)}i?.throwIfAborted();let u=o?.[a];if(!u||Object.keys(o??{}).length!==1||Array.from(u).some(e=>e.charCodeAt(0)<=31||e.charCodeAt(0)===127)||s.mode===`bearer`&&!/^Bearer [^\s]+$/.test(u))throw Error(`MCP API-key credential is unavailable.`);c={...c,[a]:u},l=async(e,t)=>{let n=new URL(typeof e==`string`?e:e instanceof URL?e.href:e.url);if(n.origin!==r.origin||n.username||n.password)throw Error(`MCP credential destination was rejected.`);return fetch(e,{...t,redirect:`error`})}}let u=this.createSdkClient(e,t===`sse`?`legacy`:`auto`),d=c?{headers:c}:void 0,f=this.createAuthProvider(e,n);await f?.prepareCallback(),i?.throwIfAborted();let p=f?new kn(f,n.url,i):void 0,m={requestInit:d,authProvider:p,...l?{fetch:l}:{}},h=t===`http`?new Ce(new URL(n.url),m):new Se(new URL(n.url),m),g=()=>{f?.cancelAuthorization(),u.close().catch(t=>this.logger.warn(`Failed to close cancelled client ${e}`,s?`API-key connection closed`:t))};i?.addEventListener(`abort`,g,{once:!0});let _=!1;try{return await u.connect(h),i?.throwIfAborted(),_=!0,{client:u,...p?{recoverAuthorization:(e,t)=>p.recover(e,t)}:{}}}catch(o){if(i?.throwIfAborted(),s)throw Error(`MCP API-key connection failed.`);if(!f||!p||!r||!(o instanceof ye)&&(!nr(o)||!f.hasPendingAuthorization()))throw o;return this.logger.info(`[oauth] Waiting for authorization of MCP server "${e}"`),a?.(!0),await p.recover(o,i,()=>{a?.(!1),this.emitServerState({serverName:e,state:`connecting`})}),i?.throwIfAborted(),await this.connectUrlSdkClient(e,t,n,!1,i,a)}finally{i?.removeEventListener(`abort`,g),_||(f?.cancelAuthorization(),await u.close().catch(t=>this.logger.warn(`Failed to close client ${e}`,s?`API-key connection closed`:t)))}}resolveAuthHeaders(e){let t={...e.headers};if(Tt(e)===`bearer`){let n=e.bearerTokenEnv?this.env?.[e.bearerTokenEnv]??Dt(e):Dt(e);n?t.Authorization=`Bearer ${n}`:this.logger.warn(`[oauth] Bearer auth configured for an MCP server but no token was resolved${e.bearerTokenEnv?` (env ${e.bearerTokenEnv} is unset)`:``}.`)}return Object.keys(t).length>0?t:void 0}createAuthProvider(e,t){return Ot({serverName:e,config:t,store:this.serverTokenStores.get(e)??this.tokenStore,logger:this.logger,callbackTimeoutMs:this.callbackTimeoutMs,workspaceRoot:this.repositoryPath,...this.callbackServer?{callbackServer:this.callbackServer}:{},onAuthorizationUrl:(e,t)=>{if(this.emitServerState({serverName:t,state:`needs-auth`}),this.onAuthorizationUrl)return this.onAuthorizationUrl(e,t);this.logger.info(`[oauth] Authorize MCP server "${t}" by visiting: ${e.toString()}`)}})}relayChildStderr(e,t){t&&(t.on(`data`,t=>{let n=t.toString(`utf8`).trimEnd();n&&this.logger.debug(`[${e}] ${n}`)}),t.on(`error`,()=>void 0))}async connectStdioSdkClient(e,t,n,r){let i=new ke({command:n.command,args:n.args,cwd:this.executionCwd?a(this.executionCwd,n.cwd??`.`):this.workspaceRoot?a(this.workspaceRoot,n.cwd??`.`):n.cwd,env:{...process.env,...this.env,...n.env,PROJECT_PATH:this.repositoryPath,[se]:Xn,[oe]:this.processOwnerId},stderr:`pipe`}),o=()=>{er({client:t,stdioTransport:i}).catch(t=>this.logger.warn(`Failed to close cancelled stdio connection for ${e}`,t))};r?.addEventListener(`abort`,o,{once:!0});try{r?.throwIfAborted(),await t.connect(i),r?.throwIfAborted(),this.relayChildStderr(e,i.stderr);let a=i.pid;if(typeof a!=`number`||a<=0)throw Error(`Failed to capture pid for stdio child process on server "${e}"`);let o=await le({repositoryPath:this.repositoryPath,serviceName:e,serviceType:`tool`,pid:a,command:n.command,args:n.args,metadata:{transport:`stdio`},ownerKind:Xn,ownerId:this.processOwnerId,resourceKey:e});return t.onclose=()=>{let t=this.clients.get(e);t instanceof sr&&t.handleStdioClosed(i)},{client:t,processLease:o,stdioTransport:i}}catch(n){try{await er({client:t,stdioTransport:i})}catch(t){this.logger.warn(`Failed to clean up incomplete stdio connection for ${e}`,t)}throw n}finally{r?.removeEventListener(`abort`,o)}}getClient(e){return this.clients.get(e)}getAllClients(){return Array.from(this.clients.values())}async disconnectServer(e){this.connectionControllers.get(e)?.abort(/* @__PURE__ */ Error(`MCP connection '${e}' was closed`));let t=this.connectionPromises.get(e);this.connectionPromises.delete(e);let n=this.clients.get(e);this.clients.delete(e),await Promise.all([t?.catch(()=>void 0),n?.close()])}async disconnectAll(){let e=[...this.clients.values()],t=[...this.connectionPromises.values()];this.clients.clear(),this.connectionPromises.clear();for(let e of this.connectionControllers.values())e.abort(/* @__PURE__ */ Error(`MCP connections were closed`));this.connectionControllers.clear();let n=(await Promise.allSettled([...e.map(e=>e.close()),...t.map(e=>e.catch(()=>void 0))])).flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(n.length)throw AggregateError(n,`Failed to close MCP connections`)}dispose(){return this.disposed=!0,this.disposePromise??=this.disconnectAll(),this.disposePromise}isConnected(e){return this.clients.get(e)?.getLifecycleState()===`connected`}getConnectionState(e){return this.clients.get(e)?.getLifecycleState()}};const lr=`install`,ur=/^(@[a-zA-Z0-9_-]+\/)?[a-zA-Z0-9._-]+(@[a-zA-Z0-9._-]+)?$/,dr=`pipe`;function fr(e){return typeof e==`object`&&!!e&&`command`in e}var pr=class{config;constructor(e){this.config=e}extractPackages(){let e=[],{mcpConfig:t,filter:n}=this.config;for(let[r,i]of Object.entries(t.mcpServers)){if(i.disabled||i.transport!==`stdio`||!fr(i.config))continue;let t=this.extractPackageInfo(r,i.config);if(t){if(n&&t.packageManager!==n)continue;e.push(t)}}return e}async prefetch(){try{let e=this.extractPackages(),t=[];if(e.length===0)return{totalPackages:0,successful:0,failed:0,results:[]};if(this.config.parallel){let n=e.map(async e=>this.prefetchPackage(e));t.push(...await Promise.all(n))}else for(let n of e){let e=await this.prefetchPackage(n);t.push(e)}let n=t.filter(e=>e.success).length,r=t.filter(e=>!e.success).length;return{totalPackages:e.length,successful:n,failed:r,results:t}}catch(e){throw Error(`Failed to prefetch packages: ${e instanceof Error?e.message:String(e)}`)}}async prefetchPackage(e){try{let[t,...n]=e.fullCommand,r=await this.runCommand(t,n);return{package:e,success:r.success,output:r.output}}catch(t){return{package:e,success:!1,output:t instanceof Error?t.message:String(t)}}}isValidPackageName(e){return ur.test(e)}extractPackageInfo(e,t){let n=t.command.toLowerCase(),r=t.args||[];if(n===`npx`||n.endsWith(`/npx`)){let t=this.extractNpxPackage(r);if(t&&this.isValidPackageName(t))return{serverName:e,packageManager:`npx`,packageName:t,fullCommand:[`npm`,lr,`-g`,t]}}if(n===`pnpx`||n.endsWith(`/pnpx`)){let t=this.extractNpxPackage(r);if(t&&this.isValidPackageName(t))return{serverName:e,packageManager:`pnpx`,packageName:t,fullCommand:[`pnpm`,`add`,`-g`,t]}}if(n===`uvx`||n.endsWith(`/uvx`)){let t=this.extractUvxPackage(r);if(t&&this.isValidPackageName(t))return{serverName:e,packageManager:`uvx`,packageName:t,fullCommand:[`uvx`,t]}}if((n===`uv`||n.endsWith(`/uv`))&&r.includes(`run`)){let t=this.extractUvRunPackage(r);if(t&&this.isValidPackageName(t))return{serverName:e,packageManager:`uv`,packageName:t,fullCommand:[`uv`,`tool`,lr,t]}}return null}extractNpxPackage(e){for(let t=0;t<e.length;t++){let n=e[t];if(n.startsWith(`--package=`))return n.slice(10)||null;if(n===`--package`&&t+1<e.length){let n=e[t+1];if(!n.startsWith(`-`))return n}if(n===`-p`&&t+1<e.length){let n=e[t+1];if(!n.startsWith(`-`))return n}}for(let t of e)if(!t.startsWith(`-`))return t;return null}extractUvxPackage(e){for(let t of e)if(!t.startsWith(`-`))return t;return null}extractUvRunPackage(e){let t=e.indexOf(`run`);if(t===-1)return null;for(let n=t+1;n<e.length;n++){let t=e[n];if(!t.startsWith(`-`))return t}return null}runCommand(e,t){return new Promise(n=>{let r=ie(e,t,{stdio:[`ignore`,dr,dr],shell:process.platform===`win32`}),i=``,a=``;r.stdout?.on(`data`,e=>{i+=e.toString()}),r.stderr?.on(`data`,e=>{a+=e.toString()}),r.on(`close`,e=>{n({success:e===0,output:i||a})}),r.on(`error`,e=>{n({success:!1,output:e.message})})})}};const mr=`.runtime.json`;async function hr(e){await g(e,{recursive:!0,mode:448});try{await m(e,448)}catch{}}function gr(e){return typeof e==`object`&&!!e}function _r(e){return gr(e)?typeof e.serverId==`string`&&typeof e.host==`string`&&typeof e.port==`number`&&e.transport===`http`&&typeof e.shutdownToken==`string`&&typeof e.startedAt==`string`&&typeof e.pid==`number`&&(e.configPath===void 0||typeof e.configPath==`string`)&&(e.runtimeLifecycle===void 0||e.runtimeLifecycle===`manual`||e.runtimeLifecycle===`stdio-http-managed`):!1}function vr(e){return e instanceof Error?e.message:String(e)}function yr(e){try{return process.kill(e,0),!0}catch{return!1}}var K=class e{runtimeDir;logger;constructor(t,n=console){this.runtimeDir=t??e.getDefaultRuntimeDir(),this.logger=n}static getDefaultRuntimeDir(){return i(E(),`.mcp-proxy`,`runtimes`)}getRecordPath(e){return i(this.runtimeDir,`${e}${mr}`)}async write(e){await hr(this.runtimeDir);let t=this.getRecordPath(e.serverId);await T(t,JSON.stringify(e,null,2),{encoding:`utf-8`,mode:384})}async read(e){let t=this.getRecordPath(e);try{let e=await y(t,`utf-8`),n=JSON.parse(e);return _r(n)?n:null}catch(n){if(gr(n)&&`code`in n&&n.code===`ENOENT`)return null;throw Error(`Failed to read runtime state for server '${e}' from '${t}': ${vr(n)}`)}}async list(){try{let e=(await b(this.runtimeDir,{withFileTypes:!0})).filter(e=>e.isFile()&&e.name.endsWith(mr));return(await Promise.all(e.map(async e=>{try{let t=await y(i(this.runtimeDir,e.name),`utf-8`),n=JSON.parse(t);return _r(n)?n:null}catch(t){return this.logger.debug(`Skipping unreadable runtime state file ${e.name}`,t),null}}))).filter(e=>e!==null)}catch(e){if(gr(e)&&`code`in e&&e.code===`ENOENT`)return[];throw Error(`Failed to list runtime states from '${this.runtimeDir}': ${vr(e)}`)}}async listOrphans(e){return(await this.list()).filter(t=>!e.has(t.serverId))}async pruneStale(){let e=(await this.list()).filter(e=>!yr(e.pid));return await Promise.all(e.map(async e=>this.remove(e.serverId))),e}async remove(e){await S(this.getRecordPath(e),{force:!0})}},br=class extends Error{filePath;cause;constructor(e,t,n){super(e),this.filePath=t,this.cause=n,this.name=`SkillLoadError`}};async function xr(e){try{return await p(e),!0}catch(t){if(t instanceof Error&&`code`in t&&t.code===`ENOENT`)return!1;throw Error(`Failed to check path existence for "${e}": ${t instanceof Error?t.message:`Unknown error`}`)}}var Sr=class{cwd;skillPaths;cachedSkills=null;skillsByName=null;watchers=[];pollingTimers=[];onCacheInvalidated;logger;constructor(e,t,n,r=console){this.cwd=e,this.skillPaths=t,this.onCacheInvalidated=n?.onCacheInvalidated,this.logger=r}async getSkills(){if(this.cachedSkills!==null)return this.cachedSkills;let e=[],t=/* @__PURE__ */ new Set,n=await Promise.all(this.skillPaths.map(async e=>{let t=r(e)?e:i(this.cwd,e);return this.loadSkillsFromDirectory(t,`project`)}));for(let r of n)for(let n of r)t.has(n.name)||(e.push(n),t.add(n.name));return this.cachedSkills=e,this.skillsByName=new Map(e.map(e=>[e.name,e])),e}async getSkill(e){return this.skillsByName===null&&await this.getSkills(),this.skillsByName?.get(e)}clearCache(){this.cachedSkills=null,this.skillsByName=null}async startWatching(){this.stopWatching();let e=await Promise.all(this.skillPaths.map(async e=>{let t=r(e)?e:i(this.cwd,e);return{skillsDir:t,exists:await xr(t)}}));for(let{skillsDir:t,exists:n}of e){if(!n)continue;let e=new AbortController;this.watchers.push(e),this.watchDirectory(t,e.signal).catch(n=>{if(n?.name!==`AbortError`){if(this.isWatchResourceLimitError(n)){this.startPollingDirectory(t,e.signal);return}this.logger.warn(`[skill-watcher] Error watching ${t}: ${n instanceof Error?n.message:`Unknown error`}`)}})}}stopWatching(){for(let e of this.watchers)e.abort();this.watchers=[];for(let e of this.pollingTimers)clearInterval(e);this.pollingTimers=[]}async watchDirectory(e,t){let n=te(e,{recursive:!0,signal:t});for await(let e of n)e.filename?.endsWith(`SKILL.md`)&&this.invalidateCache()}invalidateCache(){this.clearCache(),this.onCacheInvalidated?.()}isWatchResourceLimitError(e){return e instanceof Error&&`code`in e&&(e.code===`EMFILE`||e.code===`ENOSPC`)}startPollingDirectory(e,t){this.createSkillSnapshot(e).then(n=>{let r=n,i=setInterval(()=>{t.aborted?clearInterval(i):this.createSkillSnapshot(e).then(e=>{this.snapshotsEqual(r,e)||(r=e,this.invalidateCache())}).catch(t=>{this.logger.warn(`[skill-watcher] Polling failed for ${e}: ${t instanceof Error?t.message:`Unknown error`}`)})},3e3);this.pollingTimers.push(i),t.addEventListener(`abort`,()=>{clearInterval(i),this.pollingTimers=this.pollingTimers.filter(e=>e!==i)},{once:!0})})}async createSkillSnapshot(e){let t=/* @__PURE__ */ new Map;return await this.collectSkillSnapshots(e,t),t}async collectSkillSnapshots(e,t){let n;try{n=await b(e)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}await Promise.all(n.map(async n=>{let r=i(e,n),a=await C(r);a.isDirectory()?await this.collectSkillSnapshots(r,t):n===`SKILL.md`&&t.set(r,a.mtimeMs)}))}snapshotsEqual(e,t){if(e.size!==t.size)return!1;for(let[n,r]of e)if(t.get(n)!==r)return!1;return!0}async loadSkillsFromDirectory(e,t){let n=[];try{if(!await xr(e))return n}catch(t){throw new br(`Cannot access skills directory: ${t instanceof Error?t.message:`Unknown error`}`,e,t instanceof Error?t:void 0)}let r;try{r=await b(e)}catch(t){throw new br(`Failed to read skills directory: ${t instanceof Error?t.message:`Unknown error`}`,e,t instanceof Error?t:void 0)}let a=await Promise.all(r.map(async t=>{let n=i(e,t);try{return{entry:t,entryPath:n,stat:await C(n),error:null}}catch(e){return this.logger.warn(`Skipping entry ${n}: ${e instanceof Error?e.message:`Unknown error`}`),{entry:t,entryPath:n,stat:null,error:e}}})),o=[];for(let{entry:e,entryPath:t,stat:n}of a)if(n){if(n.isDirectory()){let e=i(t,`SKILL.md`);o.push({filePath:e,isRootLevel:!1})}else e===`SKILL.md`&&o.push({filePath:t,isRootLevel:!0})}let s=await Promise.all(o.map(async({filePath:e,isRootLevel:n})=>{try{return!n&&!await xr(e)?null:await this.loadSkillFile(e,t)}catch(t){return this.logger.warn(`Skipping skill at ${e}: ${t instanceof Error?t.message:`Unknown error`}`),null}}));for(let e of s)e&&n.push(e);return n}async loadSkillFile(e,t){let r;try{r=await y(e,`utf-8`)}catch(t){throw new br(`Failed to read skill file: ${t instanceof Error?t.message:`Unknown error`}`,e,t instanceof Error?t:void 0)}let{frontMatter:i,content:a}=hn(r);return!i||!i.name||!i.description?null:{name:i.name,description:i.description,location:t,content:a,basePath:n(e)}}};const Cr=/* @__PURE__ */ new Set([`localhost`,`127.0.0.1`,`::1`]);function wr(e){return e}function Tr(e){if(typeof e!=`object`||!e)return!1;let t=wr(e);return`status`in t&&t.status===`ok`&&`transport`in t&&t.transport===`http`&&(!(`serverId`in t)||t.serverId===void 0||typeof t.serverId==`string`)&&(!(`runtimeLifecycle`in t)||t.runtimeLifecycle===void 0||t.runtimeLifecycle===`manual`||t.runtimeLifecycle===`stdio-http-managed`)}function Er(e){if(typeof e!=`object`||!e)return!1;let t=wr(e);return`ok`in t&&typeof t.ok==`boolean`&&`message`in t&&typeof t.message==`string`&&(!(`serverId`in t)||t.serverId===void 0||typeof t.serverId==`string`)}function Dr(e,t){if(!Cr.has(e.host))throw Error(`Refusing to connect to non-loopback host '${e.host}'. Only ${Array.from(Cr).join(`, `)} are allowed.`);return`http://${e.host}:${e.port}${t}`}function Or(e){return e instanceof Error?e.message:String(e)}function kr(e){return new Promise(t=>{setTimeout(t,e)})}var Ar=class{runtimeStateService;logger;constructor(e=new K,t=console){this.runtimeStateService=e,this.logger=t}async stop(e){let t=e.timeoutMs??5e3;await this.pruneStaleRuntimeRecords();let n=await this.resolveRuntime(e),r=await this.fetchHealth(n,t);if(!r.reachable)throw await this.runtimeStateService.remove(n.serverId),Error(`Runtime '${n.serverId}' is not reachable at http://${n.host}:${n.port}. Removed stale runtime record.`);if(!e.force&&r.payload?.serverId&&r.payload.serverId!==n.serverId)throw Error(`Refusing to stop runtime at http://${n.host}:${n.port}: expected server ID '${n.serverId}' but health endpoint reported '${r.payload.serverId}'. Use --force to override.`);let i=e.token??n.shutdownToken;if(!i)throw Error(`No shutdown token available for runtime '${n.serverId}'.`);let a=await this.requestShutdown(n,i,t);return await this.waitForShutdown(n,t),await this.runtimeStateService.remove(n.serverId),{ok:!0,serverId:n.serverId,host:n.host,port:n.port,message:a.message}}async resolveRuntime(e){if(e.serverId){let t=await this.runtimeStateService.read(e.serverId);if(!t)throw Error(`No runtime record found for server ID '${e.serverId}'. Start the server with 'po-mcp-proxy mcp-serve --type http' first.`);return t}if(e.host===void 0||e.port===void 0)throw Error(`Provide --id or both --host and --port to select a runtime.`);let t=(await this.runtimeStateService.list()).filter(t=>t.host===e.host&&t.port===e.port);if(t.length===0)throw Error(`No runtime record found for http://${e.host}:${e.port}. Start the server with 'po-mcp-proxy mcp-serve --type http' first.`);if(t.length>1)throw Error(`Multiple runtime records match http://${e.host}:${e.port}. Retry with --id to avoid stopping the wrong server.`);return t[0]}async pruneStaleRuntimeRecords(){if(this.runtimeStateService.pruneStale)try{await this.runtimeStateService.pruneStale()}catch(e){this.logger.debug(`Failed to prune stale runtime records before stop resolution`,e)}}async fetchHealth(e,t){try{let n=await this.fetchWithTimeout(Dr(e,`/health`),{method:`GET`},t);if(!n.ok)return{reachable:!1};let r=await n.json();if(!Tr(r))throw Error(`Received invalid health response payload.`);return{reachable:!0,payload:r}}catch(t){return this.logger.debug(`Health check failed for ${e.serverId}`,t),{reachable:!1}}}async requestShutdown(e,t,n){let r=await this.fetchWithTimeout(Dr(e,`/admin/shutdown`),{method:`POST`,headers:{Authorization:`Bearer ${t}`}},n),i=await r.json();if(!Er(i))throw Error(`Received invalid shutdown response payload.`);if(!r.ok||!i.ok)throw Error(i.message);return i}async waitForShutdown(e,t){let n=Date.now()+t;for(;Date.now()<n;){if(!(await this.fetchHealth(e,Math.max(250,n-Date.now()))).reachable)return;await kr(200)}throw Error(`Timed out waiting for runtime '${e.serverId}' to stop at http://${e.host}:${e.port}.`)}async fetchWithTimeout(e,t,n){let r=new AbortController,i=setTimeout(()=>{r.abort()},n);try{return await fetch(e,{...t,signal:r.signal})}catch(t){throw Error(`Request to '${e}' failed: ${Or(t)}`)}finally{clearTimeout(i)}}};function q(e){return e instanceof Error?e.message:String(e)}function jr(e,t){let n=Buffer.from(e,`utf-8`),r=Buffer.from(t,`utf-8`);return n.length===r.length&&d(n,r)}var Mr=class{requests=/* @__PURE__ */ new Map;isAllowed(e){let t=Date.now()-6e4,n=(this.requests.get(e)??[]).filter(e=>e>t);return n.length>=5?(this.requests.set(e,n),!1):(n.push(Date.now()),this.requests.set(e,n),!0)}},Nr=class{honoApp=new Le;adminRateLimiter=new Mr;config;mcpHandler;nodeMcpHandler;adminOptions;logger;server=null;lastRequestAt=Date.now();activeRequests=0;idleTimer=null;constructor(e,t,n,r=console){this.config={mode:t.mode,host:t.host??`localhost`,port:t.port},this.adminOptions=n,this.logger=r,this.mcpHandler=me(e,{legacy:`reject`,onerror:e=>this.logger.error(`MCP handler failed: ${e.message}`)}),this.nodeMcpHandler=Ie(this.mcpHandler,{onerror:e=>this.logger.error(`Failed to adapt MCP request: ${e.message}`)}),this.setupHonoRoutes()}setupHonoRoutes(){this.honoApp.get(`/health`,e=>{let t={status:`ok`,transport:`http`,serverId:this.adminOptions?.serverId,runtimeLifecycle:this.adminOptions?.runtimeLifecycle,protocolVersion:`2026-07-28`,runtimeEpoch:`modern-2026-07-28-v1`};return e.json(t)}),this.honoApp.post(`/admin/shutdown`,async e=>{try{let t=e.req.header(`x-forwarded-for`)??`unknown`;if(!this.adminRateLimiter.isAllowed(t)){let t={ok:!1,message:`Too many shutdown requests. Try again later.`,serverId:this.adminOptions?.serverId};return e.json(t,429)}return await this.handleAdminShutdownRequest(e)}catch(t){this.logger.error(`Failed to process shutdown request: ${q(t)}`);let n={ok:!1,message:`Failed to process shutdown request.`,serverId:this.adminOptions?.serverId};return e.json(n,500)}})}isAuthorizedShutdownRequest(e){let t=this.adminOptions?.shutdownToken;if(!t)return!1;let n=e.authorization;if(typeof n==`string`&&n.startsWith(`Bearer `))return jr(n.slice(7),t);let r=e[`x-mcp-proxy-shutdown-token`];return typeof r==`string`&&jr(r,t)}async handleAdminShutdownRequest(e){if(!this.adminOptions?.onShutdownRequested)return e.json({ok:!1,message:`Shutdown endpoint is not enabled for this server instance.`,serverId:this.adminOptions?.serverId},404);if(!this.isAuthorizedShutdownRequest({authorization:e.req.header(`authorization`),"x-mcp-proxy-shutdown-token":e.req.header(`x-mcp-proxy-shutdown-token`)}))return e.json({ok:!1,message:`Unauthorized shutdown request: invalid or missing shutdown token.`,serverId:this.adminOptions?.serverId},401);let t=e.json({ok:!0,message:`Shutdown request accepted. Stopping server gracefully.`,serverId:this.adminOptions?.serverId});return this.adminOptions.onShutdownRequested().catch(e=>{this.logger.error(`Shutdown request failed: ${q(e)}`)}),t}async handleMcpRequest(e,t){this.activeRequests+=1;try{await this.nodeMcpHandler(e,t)}catch(e){this.logger.error(`MCP request failed: ${q(e)}`),t.headersSent||(t.writeHead(500,{"Content-Type":`application/json`}),t.end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32603,message:`MCP request failed.`},id:null})))}finally{--this.activeRequests,this.lastRequestAt=Date.now()}}startIdleShutdownMonitor(){let e=this.adminOptions?.idleShutdownMs??0;e<=0||this.idleTimer||(this.lastRequestAt=Date.now(),this.idleTimer=setInterval(()=>{this.shutdownWhenIdle(e)},Math.min(e,6e4)))}stopIdleShutdownMonitor(){this.idleTimer&&=(clearInterval(this.idleTimer),null)}async shutdownWhenIdle(e){let t=this.adminOptions?.onShutdownRequested;if(!(!t||this.activeRequests>0||Date.now()-this.lastRequestAt<e)){this.stopIdleShutdownMonitor(),this.logger.info(`Stopping idle HTTP runtime after ${e}ms without active requests`);try{await t()}catch(e){this.logger.error(`Failed to stop idle HTTP runtime: ${q(e)}`)}}}async start(){if(this.server)throw Error(`HTTP transport is already running`);let e=Fe(this.honoApp.fetch),t=f((t,n)=>{this.lastRequestAt=Date.now(),new URL(t.url??`/`,`http://${t.headers.host??this.config.host}`).pathname===`/mcp`?this.handleMcpRequest(t,n):e(t,n)});try{t.listen(this.config.port,this.config.host),await Promise.race([Me(t,`listening`),Me(t,`error`).then(([e])=>Promise.reject(e))]),this.server=t,this.startIdleShutdownMonitor(),this.logger.info(`@agimon-ai/po-mcp-proxy MCP server started on http://${this.config.host}:${this.config.port}/mcp`),this.logger.info(`Health check: http://${this.config.host}:${this.config.port}/health`)}catch(e){throw t.close(),Error(`Failed to start HTTP transport: ${q(e)}`,{cause:e})}}async stop(){this.stopIdleShutdownMonitor();let e=this.server;if(e){this.server=null,await this.mcpHandler.close();try{await Pe(e.close.bind(e))()}catch(e){throw Error(`Failed to stop HTTP transport: ${q(e)}`,{cause:e})}}}getPort(){let e=this.server?.address();return e&&typeof e==`object`?e.port:this.config.port}getHost(){return this.config.host}};const Pr=`localhost`,Fr=12e4,Ir=`MCP_PROXY_RUNTIME_DETACHED`;function Lr(){return process.env[Ir]===`1`}async function Rr(e){return(await new ce(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:e,serviceName:`mcp-proxy-http`,liveOnly:!0})).filter(e=>!!(e.host&&e.port)).map(e=>{let t=e.metadata;return{host:e.host,port:e.port,serverId:t?.serverId??`unknown`,runtimeLifecycle:t?.runtimeLifecycle===`stdio-http-managed`||t?.runtimeLifecycle===`manual`?t.runtimeLifecycle:void 0,createdAt:e.createdAt}}).sort((e,t)=>(e.createdAt??``).localeCompare(t.createdAt??``))}async function zr(e){let t=await Rr(e);for(let e of t)if(Br(await Vr(e.host,e.port)))return e;return null}function Br(e){return e.ok&&e.payload?.status===`ok`&&e.payload.transport===`http`&&e.payload.protocolVersion===`2026-07-28`&&e.payload.runtimeEpoch===`modern-2026-07-28-v1`}async function Vr(e,t,n={}){let r=n.timeoutMs??1500,i=n.retries??2,a=n.retryDelayMs??150,o=i+1,s=`unknown error`;for(let n=1;n<=o;n+=1){try{let i=await fetch(`http://${e}:${t}/health`,{signal:AbortSignal.timeout(r)});if(i.ok)return{ok:!0,payload:await i.json().catch(()=>null)??void 0,attempts:n};s=`health endpoint returned status ${i.status}`}catch(e){s=e instanceof Error?e.message:String(e)}n<o&&await new Promise(e=>setTimeout(e,a))}return{ok:!1,error:s,attempts:o}}function Hr(){let n=ae(import.meta.url),r=t.dirname(n),i=[t.resolve(r,`cli.mjs`),t.resolve(r,`..`,`dist`,`cli.mjs`),t.resolve(r,`..`,`..`,`dist`,`cli.mjs`)],a=[t.resolve(r,`..`,`cli.ts`),t.resolve(r,`..`,`..`,`src`,`cli.ts`)];for(let t of i)if(e(t))return{command:process.execPath,args:[t]};for(let t of a)if(e(t))return{command:process.execPath,args:[`--import`,`tsx`,t]};throw Error(`Unable to locate mcp-proxy CLI entrypoint`)}function Ur(e){if(!e)return Fr;let t=Number.parseInt(e,10);if(!Number.isInteger(t)||t<=0)throw Error(`Invalid timeout value: ${e}`);return t}async function Wr(e,t){let n=Date.now()+t;for(;Date.now()<n;){try{await p(e);return}catch{}await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for runtime state file: ${e}`)}async function Gr(e,t){let n=new K,r=Date.now()+t;for(;Date.now()<r;){let t=await n.read(e);if(t&&Br(await Vr(t.host,t.port,{retries:0})))return{host:t.host,port:t.port};await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for HTTP runtime '${e}' to become healthy`)}function Kr(e,t,n){let{command:r,args:i}=Hr(),a=ie(r,[...i,...e],{detached:!0,cwd:n,stdio:`ignore`,env:t});return a.unref(),a}async function qr(e){let n=e.id||mn(),r=Ur(e.timeoutMs),i=e.registryPath||e.registryDir,a=j();await new K().pruneStale();let o=await zr(a);if(o)return{host:o.host,port:o.port,serverId:o.serverId,workspaceRoot:a,reusedExistingRuntime:!0,runtimeLifecycle:o.runtimeLifecycle??`manual`};let s=e.port,c=await Rr(a);if(e.id&&c.some(e=>e.serverId===n))throw Error(`Runtime ID '${n}' belongs to an incompatible HTTP runtime; choose a new ID`);if(s!==void 0&&c.some(t=>t.host===(e.host||Pr)&&t.port===s))throw Error(`Port ${s} belongs to a different HTTP runtime; choose a free port`);let l=s,u={...process.env,[Ir]:`1`,...e.runtimeLifecycle?{MCP_PROXY_RUNTIME_LIFECYCLE:e.runtimeLifecycle}:{},...i?{PORT_REGISTRY_PATH:i,PROCESS_REGISTRY_PATH:ue(i,`processes.json`)}:{}},d=Kr([`mcp-serve`,`--type`,`http`,`--id`,n,`--host`,e.host||Pr,...l===void 0?[]:[`--port`,String(l)],...dn(e.config).flatMap(e=>[`--config`,e]),...e.cache===!1?[`--no-cache`]:[],...e.definitionsCache?[`--definitions-cache`,e.definitionsCache]:[],...e.clearDefinitionsCache?[`--clear-definitions-cache`]:[],...e.idleShutdownMinutes===void 0?[]:[`--idle-shutdown-minutes`,String(e.idleShutdownMinutes)],`--proxy-mode`,e.proxyMode],u,a),f=new Promise((e,t)=>{d.once(`exit`,(e,n)=>{t(/* @__PURE__ */ Error(`Background runtime exited before becoming healthy (code=${e??`null`}, signal=${n??`null`})`))})}),p=t.join(K.getDefaultRuntimeDir(),`${n}.runtime.json`);try{await Promise.race([Wr(p,r),f]);let{host:t,port:i}=await Promise.race([Gr(n,r),f]);return{host:t,port:i,serverId:n,workspaceRoot:a,reusedExistingRuntime:!1,runtimeLifecycle:e.runtimeLifecycle??`manual`}}catch(e){throw Error(`Failed to prestart HTTP runtime '${n}': ${e instanceof Error?e.message:String(e)}`,{cause:e})}}function Jr(e){process.stdout.write(`mcp-proxy HTTP runtime ready at http://${e.host}:${e.port} (${e.serverId})\n`),process.stdout.write(`runtimeId=${e.serverId}\n`),process.stdout.write(`runtimeUrl=http://${e.host}:${e.port}\n`),process.stdout.write(`workspaceRoot=${e.workspaceRoot}\n`)}var Yr=`0.0.1-alpha.21`,Xr=`<toolkit id="{{ serverId }}">
|
|
10
|
+
<instruction>
|
|
11
|
+
Before you use any capabilities below, you MUST call this tool with a list of names to learn how to use them properly; this includes:
|
|
12
|
+
- For tools: Arguments schema needed to pass to use_tool
|
|
13
|
+
- For skills: Detailed instructions that will expand when invoked (Prefer to be explored first when relevant)
|
|
14
|
+
|
|
15
|
+
This tool is optimized for batch queries - you can request multiple capabilities at once for better performance.
|
|
16
|
+
|
|
17
|
+
How to invoke:
|
|
18
|
+
- For MCP tools: Use use_tool with toolName and toolArgs based on the schema
|
|
19
|
+
- For skills: Use this tool with the skill name to get expanded instructions
|
|
20
|
+
</instruction>
|
|
21
|
+
|
|
22
|
+
<available_capabilities>
|
|
23
|
+
{% for server in servers -%}
|
|
24
|
+
<group original-mcp-server="{{ server.name }}">
|
|
25
|
+
{% if server.instruction -%}
|
|
26
|
+
<group_instruction>{{ server.instruction }}</group_instruction>
|
|
27
|
+
{% endif -%}
|
|
28
|
+
{% if server.omitToolDescription -%}
|
|
29
|
+
{% for toolName in server.toolNames -%}
|
|
30
|
+
<item name="{{ toolName }}"></item>
|
|
31
|
+
{% endfor -%}
|
|
32
|
+
{% else -%}
|
|
33
|
+
{% for tool in server.tools -%}
|
|
34
|
+
<item name="{{ tool.displayName }}"><description>{{ tool.description | default: "No description" }}</description></item>
|
|
35
|
+
{% endfor -%}
|
|
36
|
+
{% endif -%}
|
|
37
|
+
</group>
|
|
38
|
+
{% endfor -%}
|
|
39
|
+
{% if skills.size > 0 -%}
|
|
40
|
+
<group name="skills">
|
|
41
|
+
{% for skill in skills -%}
|
|
42
|
+
<item name="{{ skill.displayName }}"><description>{{ skill.description }}</description></item>
|
|
43
|
+
{% endfor -%}
|
|
44
|
+
</group>
|
|
45
|
+
{% endif -%}
|
|
46
|
+
</available_capabilities>
|
|
47
|
+
</toolkit>
|
|
48
|
+
`;function Zr(e,t){return`<command-message>The "${e}" skill is loading</command-message>\n${t}`}const J=O.object({toolNames:O.array(O.string().min(1)).min(1).describe(`List of tool names to get detailed information about`)});var Y=class e{static TOOL_NAME=`describe_tools`;clientManager;skillService;definitionsCacheService;liquid=new Re;serverId;constructor(e,t,n,r){this.clientManager=e,this.skillService=t,this.serverId=n||`unknown`,this.definitionsCacheService=r||new U(e,t)}clearAutoDetectedSkillsCache(){this.definitionsCacheService.clearLiveCache()}async collectPromptSkills(){let e=[],t=await this.definitionsCacheService.getServerDefinitions();for(let n of t)for(let t of n.promptSkills)e.push({name:t.skill.name,displayName:t.skill.name,description:t.skill.description});return e}async findPromptSkill(e){if(e)return await this.definitionsCacheService.getPromptSkillByName(e)}async getPromptSkillContent(e){let t=await this.findPromptSkill(e);if(t)try{let e=(await(await this.clientManager.ensureConnected(t.serverName)).getPrompt(t.promptName)).messages?.map(e=>{let t=e.content;return typeof t==`string`?t:t&&typeof t==`object`&&`text`in t?String(t.text):``}).join(`
|
|
49
|
+
`)||``;return{name:t.skill.name,location:t.skill.folder||`prompt:${t.serverName}/${t.promptName}`,instructions:Zr(t.skill.name,e)}}catch(t){console.error(`Failed to get prompt-based skill '${e}': ${t instanceof Error?t.message:`Unknown error`}`);return}}async buildToolkitDescription(){let e=await this.definitionsCacheService.getServerDefinitions(),t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.tools)t.has(e.name)||t.set(e.name,[]),t.get(e.name)?.push(n.serverName);let n=(e,n)=>(t.get(e)||[]).length>1?`${n}__${e}`:e,r=/* @__PURE__ */ new Set,i=e.map(e=>{let t=e.tools.map(t=>({displayName:n(t.name,e.serverName),description:t.description}));for(let e of t)r.add(e.displayName);return{name:e.serverName,instruction:e.serverInstruction,omitToolDescription:e.omitToolDescription||!1,tools:t,toolNames:t.map(e=>e.displayName)}}),[a,o,s]=await Promise.all([this.skillService?this.skillService.getSkills():Promise.resolve([]),this.definitionsCacheService.getCachedFileSkills(),this.collectPromptSkills()]),c=/* @__PURE__ */ new Set,l=[];for(let e of a)c.has(e.name)||(c.add(e.name),l.push({name:e.name,displayName:e.name,description:e.description}));for(let e of o)c.has(e.name)||(c.add(e.name),l.push({name:e.name,displayName:e.name,description:e.description}));for(let e of s)c.has(e.name)||(c.add(e.name),l.push(e));let u=l.map(e=>{let t=r.has(e.name);return{name:e.name,displayName:t?`skill__${e.name}`:e.name,description:e.description}});return{content:await this.liquid.parseAndRender(Xr,{servers:i,skills:u,serverId:this.serverId}),toolNames:r}}getInputSchema(){return J}async getDefinition(){let{content:t}=await this.buildToolkitDescription();return{name:e.TOOL_NAME,description:t,inputSchema:O.toJSONSchema(J,{reused:`inline`})}}async runLookups(e,t){let n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map;for(let e of t){let t=e.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}));n.set(e.serverName,t);for(let n of t)r.has(n.name)||r.set(n.name,[]),r.get(n.name)?.push(e.serverName)}let i=await Promise.all(e.map(async e=>{let t={tools:[],skills:[],notFound:null};if(e.startsWith(`skill__`)){let n=e.slice(7);if(this.skillService){let e=await this.skillService.getSkill(n);if(e)return t.skills.push({name:e.name,location:e.basePath,instructions:Zr(e.name,e.content)}),t}let r=await this.getPromptSkillContent(n);return r?(t.skills.push(r),t):(t.notFound=e,t)}let{serverName:i,actualToolName:a}=B(e);if(i){let r=n.get(i);if(!r){try{let n=(await(await this.clientManager.ensureConnected(i)).listTools()).find(e=>e.name===a);n?t.tools.push({server:i,tool:{name:n.name,description:n.description,inputSchema:n.inputSchema}}):t.notFound=e}catch{t.notFound=e}return t}let o=r.find(e=>e.name===a);return o?t.tools.push({server:i,tool:{name:o.name,description:o.description,inputSchema:o.inputSchema}}):t.notFound=e,t}let o=r.get(a);if(!o||o.length===0){if(this.skillService){let e=await this.skillService.getSkill(a);if(e)return t.skills.push({name:e.name,location:e.basePath,instructions:Zr(e.name,e.content)}),t}let n=await this.getPromptSkillContent(a);return n?(t.skills.push(n),t):(t.notFound=e,t)}for(let e of o){let r=n.get(e).find(e=>e.name===a);t.tools.push({server:e,tool:{name:r.name,description:r.description,inputSchema:r.inputSchema}})}return t})),a=[],o=[],s=[];for(let e of i)a.push(...e.tools),o.push(...e.skills),e.notFound&&s.push(e.notFound);return{foundTools:a,foundSkills:o,notFoundItems:s}}async execute(e){try{let{toolNames:t}=J.parse(e);if(!t||t.length===0)return{content:[{type:`text`,text:`No tool names provided. Please specify at least one tool name.`}],isError:!0};let n=await this.runLookups(t,await this.definitionsCacheService.getServerDefinitions());n.notFoundItems.length>0&&(this.definitionsCacheService.clearLiveCache(),await this.definitionsCacheService.collectForCache(),n=await this.runLookups(t,await this.definitionsCacheService.getServerDefinitions()));let{foundTools:r,foundSkills:i,notFoundItems:a}=n;if(r.length===0&&i.length===0)return{content:[{type:`text`,text:`None of the requested tools/skills found.\nRequested: ${t.join(`, `)}\nUse describe_tools to see available tools and skills.`}],isError:!0};let o={},s=[];return r.length>0&&(o.tools=r,s.push(`For MCP tools: Use the use_tool function with toolName and toolArgs based on the inputSchema above.`)),i.length>0&&(o.skills=i,s.push(`For skill, just follow skill's description to continue.`)),s.length>0&&(o.nextSteps=s),a.length>0&&(o.notFound=a,o.warnings=[`Items not found: ${a.join(`, `)}`]),{content:[{type:`text`,text:JSON.stringify(o,null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error describing tools: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}};function Qr(e){let t=e._meta?.[`agiflowai/capabilities`];return Array.isArray(t)?t.filter(e=>typeof e==`string`):[]}function $r(e){return Array.from(new Set(e.flatMap(e=>Qr(e)))).sort()}const ei=O.object({capability:O.string().optional().describe(`Optional capability filter. Matches explicit capability tags first, then server summaries, server names, tool names, and tool descriptions.`),serverName:O.string().optional().describe(`Optional server name filter.`)});var ti=class e{_clientManager;definitionsCacheService;static TOOL_NAME=`list_tools`;constructor(e,t){this._clientManager=e,this.definitionsCacheService=t}formatToolName(e,t,n){return(n.get(e)||[]).length>1?`${t}__${e}`:e}getInputSchema(){return ei}async getDefinition(){let t=await this.definitionsCacheService.getServerDefinitions(),n=t.length>0?t.map(e=>{let t=$r(e.tools),n=t.length>0?t.join(`, `):e.serverInstruction||`No capability summary available`;return`${e.serverName}: ${n}`}).join(`
|
|
50
|
+
`):`No proxied servers available.`;return{name:e.TOOL_NAME,description:`Search proxied MCP tools by server capability summary.\n\nAvailable capabilities:\n${n}`,inputSchema:O.toJSONSchema(ei,{reused:`inline`})}}async execute(e){let t=ei.parse(e),n=await this.definitionsCacheService.getServerDefinitions(),r=t.capability?.trim().toLowerCase(),i=t.serverName?.trim().toLowerCase(),a=/* @__PURE__ */ new Map;for(let e of n)for(let t of e.tools)a.has(t.name)||a.set(t.name,[]),a.get(t.name)?.push(e.serverName);let o=n.filter(e=>i&&e.serverName.toLowerCase()!==i?!1:!r||(e.serverInstruction?.toLowerCase()||``).includes(r)||$r(e.tools).some(e=>e.toLowerCase().includes(r))?!0:e.tools.some(t=>{let n=this.formatToolName(t.name,e.serverName,a),i=Qr(t);return n.toLowerCase().includes(r)||(t.description||``).toLowerCase().includes(r)||i.some(e=>e.toLowerCase().includes(r))})).map(e=>({server:e.serverName,capabilities:$r(e.tools),summary:e.serverInstruction,tools:e.tools.map(t=>({name:this.formatToolName(t.name,e.serverName,a),description:e.omitToolDescription?void 0:t.description,capabilities:Qr(t)}))})).filter(e=>e.tools.length>0);return{content:[{type:`text`,text:JSON.stringify({servers:o},null,2)}],isError:o.length===0||void 0}}};const X=O.object({toolName:O.string().min(1).describe(`Name of the tool to execute`),toolArgs:O.record(O.string(),O.unknown()).optional().describe(`Arguments to pass to the tool, as discovered from describe_tools`)});var Z=class e{static TOOL_NAME=`use_tool`;clientManager;skillService;definitionsCacheService;serverId;constructor(e,t,n,r){this.clientManager=e,this.skillService=t,this.definitionsCacheService=r||new U(e,t),this.serverId=n||`unknown`}getInputSchema(){return X}getDefinition(){return{name:e.TOOL_NAME,description:`Execute an MCP tool (NOT Skill) with provided arguments. You MUST call describe_tools first to discover the tool's correct arguments. Then to use tool:
|
|
51
|
+
- Provide toolName and toolArgs based on the schema
|
|
52
|
+
- If multiple servers provide the same tool, specify serverName
|
|
53
|
+
|
|
54
|
+
IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverId}".
|
|
55
|
+
`,inputSchema:O.toJSONSchema(X,{reused:`inline`})}}async coerceToolArgs(e,t,n){let r=await this.definitionsCacheService.getToolSchema(e,t);if(!r)return n;let i=Be(r);return A(n,i)}executeSkill(e){return{content:[{type:`text`,text:`Skill "${e.name}" found. Skills provide instructions and should not be executed via use_tool.\n\nUse describe_tools to view the skill details at: ${e.basePath}\n\nThen follow the skill's instructions directly.`}]}}async findPromptSkill(e){if(e)return await this.definitionsCacheService.getPromptSkillByName(e)}executePromptSkill(e){let t=e.skill.folder||`prompt:${e.serverName}/${e.promptName}`;return{content:[{type:`text`,text:`Skill "${e.skill.name}" found. Skills provide instructions and should not be executed via use_tool.\n\nUse describe_tools to view the skill details at: ${t}\n\nThen follow the skill's instructions directly.`}]}}async execute(e){try{let{toolName:t,toolArgs:n={}}=X.parse(e);if(t.startsWith(`skill__`)){let e=t.slice(7);if(this.skillService){let t=await this.skillService.getSkill(e);if(t)return this.executeSkill(t)}let n=await this.findPromptSkill(e);return n?this.executePromptSkill(n):{content:[{type:`text`,text:`Skill "${e}" not found. Use describe_tools to see available skills.`}],isError:!0}}let r=this.clientManager.getKnownServerNames(),{serverName:i,actualToolName:a}=B(t);if(i)try{let e=await this.clientManager.ensureConnected(i);if(e.toolBlacklist?.includes(a))return{content:[{type:`text`,text:`Tool "${a}" is blacklisted on server "${i}" and cannot be executed.`}],isError:!0};let t=this.clientManager.getServerRequestTimeout(i),r=await this.coerceToolArgs(i,a,n);return await e.callTool(a,r,t?{timeout:t}:void 0)}catch(e){return{content:[{type:`text`,text:`Failed to call tool "${a}" on server "${i}". Available servers: ${r.join(`, `)}. ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}let o=await this.definitionsCacheService.getServersForTool(a);if(o.length===0&&(this.definitionsCacheService.clearLiveCache(),await this.definitionsCacheService.collectForCache(),o=await this.definitionsCacheService.getServersForTool(a)),o.length===0){if(this.skillService){let e=await this.skillService.getSkill(a);if(e)return this.executeSkill(e)}let e=await this.findPromptSkill(a);return e?this.executePromptSkill(e):{content:[{type:`text`,text:`Tool or skill "${a}" not found. Use describe_tools to see available tools and skills.`}],isError:!0}}if(o.length>1)return{content:[{type:`text`,text:`Tool "${a}" found on multiple servers. Use prefixed format to specify: ${o.map(e=>`${e}__${a}`).join(`, `)}`}],isError:!0};try{let e=o[0],t=await this.clientManager.ensureConnected(e),r=this.clientManager.getServerRequestTimeout(e),i=await this.coerceToolArgs(e,a,n);return await t.callTool(a,i,r?{timeout:r}:void 0)}catch(e){return{content:[{type:`text`,text:`Failed to call tool "${a}": ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}catch(e){return{content:[{type:`text`,text:`Error executing tool: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}},ni=class{server;handle=null;logger;constructor(e,t=console){this.server=e,this.logger=t}async start(){if(this.handle)throw Error(`MCP stdio server is already running`);this.handle=Ve(()=>this.server,{legacy:`reject`}),this.logger.info(`@agimon-ai/po-mcp-proxy MCP server started on stdio`)}async stop(){let e=this.handle;e&&(this.handle=null,await e.close())}};const ri=[`econnrefused`,`econnreset`,`enotfound`,`connection refused`,`fetch failed`,`socket hang up`,`network error`,`failed to fetch`];function ii(e){if(!(e instanceof Error))return!1;let t=e.message.toLowerCase();return ri.some(e=>t.includes(e))}function ai(e){let t=/* @__PURE__ */ new Set,n=[],r=e;for(;r&&!t.has(r);)if(t.add(r),r instanceof Error){let e=r;n.push({message:r.message,code:e.code}),r=e.cause}else if(typeof r==`object`){let e=r;n.push({message:typeof e.message==`string`?e.message:Ne(r),code:typeof e.code==`string`?e.code:void 0}),r=e.cause}else{n.push({message:typeof r==`string`?r:Ne(r)});break}return n}function oi(e){return ai(e).some(({message:e,code:t})=>{let n=e.toLowerCase(),r=si(t);return n.includes(`unknown session`)||n.includes(`session not found`)||n.includes(`transport closed`)||n.includes(`connection closed`)||n.includes(`socket hang up`)||n.includes(`fetch failed`)||r===`econnreset`})}function si(e){return typeof e==`string`?e.toLowerCase():void 0}var ci=class{endpoint;resolveEndpoint;stdioProxyServer=null;stdioHandle=null;httpClient=null;logger;MAX_RECONNECT_ATTEMPTS=5;RECONNECT_BASE_MS=1e3;RECONNECT_MAX_MS=3e4;constructor(e,t=console){this.endpoint=e.endpoint,this.resolveEndpoint=e.resolveEndpoint,this.logger=t}async start(){try{let e=await this.createAndConnectClient();this.httpClient=e,this.stdioProxyServer=this.createProxyServer(),this.stdioHandle=Ve(()=>this.stdioProxyServer,{legacy:`reject`}),this.logger.info(`@agimon-ai/po-mcp-proxy MCP stdio proxy connected to ${this.endpoint.toString()}`)}catch(e){throw await this.stop(),Error(`Failed to start stdio-http proxy transport: ${e instanceof Error?e.message:String(e)}`)}}async stop(){let e=this.stdioHandle,t=this.stdioProxyServer,n=this.httpClient;this.stdioHandle=null,this.stdioProxyServer=null,this.httpClient=null;let r=[];if(await Promise.all([(async()=>{try{e&&await e.close()}catch(e){r.push(`failed closing stdio transport: ${e instanceof Error?e.message:String(e)}`)}})(),(async()=>{try{t&&await t.close()}catch(e){r.push(`failed closing stdio proxy server: ${e instanceof Error?e.message:String(e)}`)}})(),(async()=>{try{n&&await n.close()}catch(e){r.push(`failed closing http client: ${e instanceof Error?e.message:String(e)}`)}})()]),r.length>0)throw Error(`Failed to stop stdio-http proxy transport: ${r.join(`; `)}`)}async createAndConnectClient(){let e=new Ce(this.endpoint),t=new ve({name:`@agimon-ai/po-mcp-proxy-stdio-http-proxy`,version:`0.1.0`},{capabilities:{},versionNegotiation:{mode:{pin:`2026-07-28`}}});return await t.connect(e),t}async reconnectWithBackoff(){for(let e=0;e<this.MAX_RECONNECT_ATTEMPTS;e++){let t=Math.min(this.RECONNECT_BASE_MS*2**e,this.RECONNECT_MAX_MS);await new Promise(e=>setTimeout(e,t));try{this.resolveEndpoint&&(this.endpoint=await this.resolveEndpoint()),await this.httpClient?.close().catch(()=>void 0);let t=await this.createAndConnectClient();this.httpClient=t,this.logger.info(`Reconnected to HTTP backend at ${this.endpoint.toString()} (attempt ${e+1})`);return}catch{this.logger.info(`Reconnect attempt ${e+1}/${this.MAX_RECONNECT_ATTEMPTS} to ${this.endpoint.toString()} failed`)}}throw Error(`Failed to reconnect to HTTP backend at ${this.endpoint.toString()} after ${this.MAX_RECONNECT_ATTEMPTS} attempts`)}async withReconnect(e,t=!0){if(!this.httpClient)throw Error(`HTTP client not connected`);try{return await e()}catch(n){if(ii(n)||oi(n)){if(await this.reconnectWithBackoff(),t)return await e();throw Error(`The connection was recovered, but the prior tool call may have executed; refusing to replay it.`,{cause:n})}throw n}}createProxyServer(){let e=new pe({name:`@agimon-ai/po-mcp-proxy-stdio-http-proxy`,version:`0.1.0`},{capabilities:{tools:{},resources:{},prompts:{}}});return e.setRequestHandler(`tools/list`,async()=>{try{return await this.withReconnect(()=>this.httpClient.listTools())}catch(e){throw Error(`Failed forwarding tools/list to HTTP backend: ${e instanceof Error?e.message:String(e)}`)}}),e.setRequestHandler(`tools/call`,async e=>{try{return await this.withReconnect(()=>this.httpClient.callTool({name:e.params.name,arguments:e.params.arguments}),!1)}catch(t){throw Error(`Failed forwarding tools/call (${e.params.name}) to HTTP backend: ${t instanceof Error?t.message:String(t)}`)}}),e.setRequestHandler(`resources/list`,async()=>{try{return await this.withReconnect(()=>this.httpClient.listResources())}catch(e){throw Error(`Failed forwarding resources/list to HTTP backend: ${e instanceof Error?e.message:String(e)}`)}}),e.setRequestHandler(`resources/read`,async e=>{try{return await this.withReconnect(()=>this.httpClient.readResource({uri:e.params.uri}))}catch(t){throw Error(`Failed forwarding resources/read (${e.params.uri}) to HTTP backend: ${t instanceof Error?t.message:String(t)}`)}}),e.setRequestHandler(`prompts/list`,async()=>{try{return await this.withReconnect(()=>this.httpClient.listPrompts())}catch(e){throw Error(`Failed forwarding prompts/list to HTTP backend: ${e instanceof Error?e.message:String(e)}`)}}),e.setRequestHandler(`prompts/get`,async e=>{try{return await this.withReconnect(()=>this.httpClient.getPrompt({name:e.params.name,arguments:e.params.arguments}))}catch(t){throw Error(`Failed forwarding prompts/get (${e.params.name}) to HTTP backend: ${t instanceof Error?t.message:String(t)}`)}}),e}};function Q(e=console,t,n,r){return{createConfigFetcherService:t=>new cn(t,e),createClientManagerService:(i,a,o,s)=>t||n||r?new cr(e,j(t??r),new jn(i),a,t?j(t):void 0,n,r,o,s):new cr(e,j(),new jn(i),a,void 0,void 0,void 0,o,s),createRuntimeStateService:t=>new K(t,e),createStopServerService:t=>new Ar(t,e),createSkillService:(t,n,r)=>new Sr(t,n,r,e),createDefinitionsCacheService:(t,n,r)=>new U(t,n,r,e),createPrefetchService:e=>new pr(e),createDescribeToolsTool:(e,t,n,r)=>new Y(e,t,n,r),createUseToolTool:(e,t,n,r)=>new Z(e,t,n,r),createSearchListToolsTool:(e,t)=>new ti(e,t),createStdioTransportHandler:async t=>new ni(await t(),e),createHttpTransportHandler:(t,n,r)=>new Nr(t,n,r,e),createStdioHttpTransportHandler:t=>new ci({endpoint:t},e)}}async function li(e,t,n,r){try{return await e.createConfigFetcherService({configSources:t,useCache:!n,env:r}).fetchConfiguration(n)}catch(e){let n=t.map(e=>e.path);throw Error(`Failed to load MCP configuration from '${n.join(`, `)}': ${e instanceof Error?e.message:String(e)}`)}}async function ui(e,t,n){let r=[];return await Promise.all(Object.entries(t).map(async([t,i])=>{try{await e.connectToServer(t,i),n.info(`Connected to MCP server: ${t}`)}catch(e){let i=e instanceof Error?e:Error(String(e));r.push({serverName:t,error:i}),n.warn(`Failed to connect to ${t}`,e)}})),r}async function di(e){let n=e?.workspaceRoot,r=e?.executionCwd;if(r!==void 0&&!t.isAbsolute(r))throw Error(`executionCwd must be an absolute directory`);let i=e?.environment?{...process.env,...e.environment}:void 0,a=j(n??r),o=await On({workspaceRoot:a,serviceName:`@agimon-ai/mcp-proxy`,env:i}),s=o,c=Q(s,n?a:void 0,e?.environment,r),l=[],u=!1,d,f=()=>d||(u=!0,d=(async()=>{let e=await Promise.allSettled(l.map(e=>Promise.resolve().then(e)));try{await o.shutdown()}catch(t){e.push({status:`rejected`,reason:t})}let t=e.flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(t.length)throw AggregateError(t,`MCP proxy disposal failed`)})(),d);try{let o,d,p,m,h=!1,g,_=e?.startupMode??`blocking`,v,y=dn(e?.configFilePath),b=(e?.configSources?.length?e.configSources:fn(y)).map(e=>n?{...e,path:t.resolve(a,e.path)}:e),x=b.map(e=>e.path),S=b.length>0?await li(c,b,e?.noCache===!0,i):void 0,C=c.createClientManagerService(An(S?.proxy?.outputGuard),e?.auth,e?.outputSchemaValidation,e?.clientCapabilities);if(l.push(()=>C.dispose()),S){if(o=S.skills,d=S.id,p=U.generateConfigHash(S),m=e?.definitionsCachePath||U.getDefaultCachePath(x),C.registerServerConfigs(S.mcpServers),e?.clearDefinitionsCache&&m&&(await U.clearFile(m),s.info(`[definitions-cache] Cleared ${m}`)),m){let e=await U.inspectFile(m,{configHash:p,oneMcpVersion:Yr});e.state===`usable`?(g=e.cache,h=!0,s.info(`[definitions-cache] Cache is usable`,{"definitions_cache.state":e.state,"definitions_cache.path":e.cachePath,"definitions_cache.server_count":Object.keys(e.cache.servers).length})):e.state===`absent`?s.info(`[definitions-cache] Cache is absent; using live discovery`,{"definitions_cache.state":e.state,"definitions_cache.path":e.cachePath}):s.warn(`[definitions-cache] Cache is invalid; using live discovery`,{"definitions_cache.state":e.state,"definitions_cache.path":e.cachePath,"definitions_cache.reason":e.reason,"definitions_cache.error":e.error})}if(h&&s.info(`[definitions-cache] Using cached definitions from ${m}`),_===`background`)v=ui(C,S.mcpServers,s).then(e=>{e.length>0&&s.warn(`MCP server connections failed: ${e.map(e=>e.serverName).join(`, `)}`)},e=>{s.warn(`[mcp-proxy] Background connection pass failed: ${e instanceof Error?e.message:String(e)}`)});else if(_!==`lazy`&&!h){let e=Object.keys(S.mcpServers).length,t=await ui(C,S.mcpServers,s);if(t.length>0&&t.length<e&&s.warn(`Warning: Some MCP server connections failed: ${t.map(e=>e.serverName).join(`, `)}`),t.length>0&&t.length===e)throw Error(`All MCP server connections failed: ${t.map(e=>`${e.serverName}: ${e.error.message}`).join(`, `)}`)}}let w=e?.serverId||d||mn();s.info(`[mcp-proxy] Server ID: ${w}`);let ee=(e?.skills||o)?.paths??[],te={describeTools:null},T=ee.length>0?c.createSkillService(r??(n?a:process.cwd()),ee,{onCacheInvalidated:()=>{te.describeTools?.clearAutoDetectedSkillsCache()}}):void 0,E=c.createDefinitionsCacheService(C,T,g?{cacheData:g}:void 0);g&&E.logCapabilitySummary(g,`cache`);let ne=e?.proxyMode||`meta`,re=c.createDescribeToolsTool(C,T,w,E),ie=c.createUseToolTool(C,T,w,E),ae=c.createSearchListToolsTool(C,E);return te.describeTools=re,T&&(l.push(()=>T.stopWatching()),T.startWatching().catch(e=>{s.warn(`[skill-watcher] File watcher failed (non-critical): ${e instanceof Error?e.message:`Unknown error`}`)})),_!==`lazy`&&!h&&m&&x.length>0&&(v??Promise.resolve()).then(()=>u?void 0:E.collectForCache({configPath:x[0],configHash:p,serverNames:Object.keys(S?.mcpServers??{}),oneMcpVersion:Yr,serverId:w})).then(e=>u||e===void 0?void 0:U.writeToFile(m,e)).then(()=>{s.info(`[definitions-cache] Wrote ${m}`)}).catch(e=>{s.warn(`[definitions-cache] Failed to persist ${m}: ${e instanceof Error?e.message:`Unknown error`}`)}),lt(),l.push(()=>ut()),{clientManager:C,definitionsCacheService:E,skillService:T,logger:s,describeTools:re,useTool:ie,searchListTools:ae,serverId:w,proxyMode:ne,connectionsSettled:v??Promise.resolve(),dispose:f}}catch(e){try{await f()}catch(t){throw AggregateError([e,t],`MCP proxy startup and cleanup failed`)}throw e}}async function fi(e){let t=await e();return Q().createStdioTransportHandler(()=>Promise.resolve(t))}function pi(e,t,n){return Q().createHttpTransportHandler(e,t,n)}function mi(e){return Q().createStdioHttpTransportHandler(e)}async function hi(e){return di(e)}function gi(e){let t=e.tools.map(e=>e.name),n=$r(e.tools),r=n.length>0?`; capabilities: ${n.join(`, `)}`:``;return t.length===0?`${e.serverName} (no tools cached${r})`:`${e.serverName} (${t.join(`, `)})${r}`}function _i(e,t){let n=[`Proxied from server "${e.serverName}" as tool "${t.name}".`];e.serverInstruction&&n.push(`Server summary: ${e.serverInstruction}`),t.description&&!e.omitToolDescription&&n.push(t.description);let r=Qr(t);return r.length>0&&n.push(`Capabilities: ${r.join(`, `)}`),n.join(`
|
|
56
|
+
|
|
57
|
+
`)}function vi(e){let t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.tools)t.has(e.name)||t.set(e.name,[]),t.get(e.name)?.push(n.serverName);let n=[];for(let r of e)for(let e of r.tools){let i=(t.get(e.name)||[]).length>1;n.push({name:i?`${r.serverName}__${e.name}`:e.name,description:_i(r,e),inputSchema:e.inputSchema,_meta:e._meta})}return n}function $(e,t){return`${e}__${t}`}function yi(e){let t=`__${Y.TOOL_NAME}`;if(e.endsWith(t)&&e.length>t.length)return{serverName:e.slice(0,-t.length),metaToolName:Y.TOOL_NAME};let n=`__${Z.TOOL_NAME}`;return e.endsWith(n)&&e.length>n.length?{serverName:e.slice(0,-n.length),metaToolName:Z.TOOL_NAME}:null}function bi(e){let t=[`Get detailed schemas for tools proxied by server "${e.serverName}".`,`Call this before using the paired use_tool for this server.`];if(e.serverInstruction&&t.push(`Server summary: ${e.serverInstruction}`),e.tools.length===0)return t.push(`Available tools: none cached.`),t.join(`
|
|
58
|
+
|
|
59
|
+
`);let n=e.tools.map(t=>e.omitToolDescription?`- ${t.name}`:`- ${t.name}: ${t.description||`No description`}`);return t.push(`Available tools:\n${n.join(`
|
|
60
|
+
`)}`),t.join(`
|
|
61
|
+
|
|
62
|
+
`)}function xi(e){let t=[];for(let n of e)t.push({name:$(n.serverName,Y.TOOL_NAME),description:bi(n),inputSchema:O.toJSONSchema(J,{reused:`inline`})}),t.push({name:$(n.serverName,Z.TOOL_NAME),description:[`Execute an MCP tool proxied by server "${n.serverName}".`,`Call ${$(n.serverName,Y.TOOL_NAME)} first to discover tool schemas.`,`Pass the downstream tool name without a server prefix in toolName.`].join(`
|
|
63
|
+
|
|
64
|
+
`),inputSchema:O.toJSONSchema(X,{reused:`inline`})});return t}function Si(e,t){if(!e)return{foundTools:[],notFoundItems:t};let n=[],r=[];for(let i of t){let t=e.tools.find(e=>e.name===i);t?n.push({name:t.name,description:t.description,inputSchema:t.inputSchema}):r.push(i)}return{foundTools:n,notFoundItems:r}}async function Ci(e,t){let[n,r]=await Promise.all([t?t.getSkills():e.getCachedFileSkills(),e.getServerDefinitions()]);return n.length>0||r.some(e=>e.promptSkills.length>0)}function wi(e,t){let n=e.length>0?e.map(gi).join(`; `):`No proxied servers available.`;return{name:Y.TOOL_NAME,description:`Get detailed skill instructions for file-based skills and prompt-based skills proxied by mcp-proxy.\n\nProxy summary: ${n}\n\nUse this when you need the full instructions for a skill. For MCP tools, call the flat tool names directly. Only use skills discovered from describe_tools with id="${t}".`,inputSchema:{type:`object`,properties:{toolNames:{type:`array`,items:{type:`string`,minLength:1},description:`List of skill names to get detailed information about`,minItems:1}},required:[`toolNames`],additionalProperties:!1}}}function Ti(e,t){let n=e.length>0?e.map(gi).join(`; `):`No proxied servers available.`;return{name:Y.TOOL_NAME,description:`Get detailed schemas and skill instructions for proxied MCP capabilities.\n\nProxy summary: ${n}\n\nUse list_tools first to search capability summaries and discover tool names. Then use describe_tools to fetch full schemas or skill instructions. Only use capabilities discovered from mcp-proxy id="${t}".`,inputSchema:{type:`object`,properties:{toolNames:{type:`array`,items:{type:`string`,minLength:1},description:`List of tool or skill names to get detailed information about`,minItems:1}},required:[`toolNames`],additionalProperties:!1}}}function Ei(e,t,n){let r=e.length>0?e.map(gi).join(`; `):`No proxied servers available.`;return t===`flat`?[`mcp-proxy proxies downstream MCP servers and exposes their tools and resources directly.`,`Proxied servers and tools: ${r}`,n?`Skills are still exposed through describe_tools when file-based skills or prompt-backed skills are configured.`:`No skills are currently exposed through describe_tools.`].join(`
|
|
65
|
+
|
|
66
|
+
`):t===`search`?[`mcp-proxy proxies downstream MCP servers in search mode.`,`Proxied servers and tools: ${r}`,`Use list_tools to search capability summaries and discover tool names, describe_tools to fetch schemas or skill instructions, and use_tool to execute tools.`].join(`
|
|
67
|
+
|
|
68
|
+
`):t===`group`?[`mcp-proxy proxies downstream MCP servers in group mode.`,`Proxied servers and tools: ${r}`,`Use each server-specific describe_tools tool to inspect schemas, then the matching server-specific use_tool tool to execute plain downstream tool names.`].join(`
|
|
69
|
+
|
|
70
|
+
`):[`mcp-proxy proxies downstream MCP servers in meta mode.`,`Proxied servers and tools: ${r}`,`Use describe_tools to inspect capabilities and use_tool to execute them.`].join(`
|
|
71
|
+
|
|
72
|
+
`)}async function Di(e){let{clientManager:t,definitionsCacheService:n,skillService:r,logger:i,describeTools:a,useTool:o,searchListTools:s,serverId:c,proxyMode:l}=e,u=await n.getServerDefinitions(),d=await Ci(n,r),f=async(e,t,n)=>i.runInSpan?i.runInSpan(e,{attributes:t},async()=>n()):await n(),p=new pe({name:`@agimon-ai/po-mcp-proxy`,version:`0.1.0`},{capabilities:{tools:{},resources:{},prompts:{}},instructions:Ei(u,l,d)});return p.setRequestHandler(`tools/list`,async()=>f(`mcp.server.list_tools`,{"mcp.service":`@agimon-ai/po-mcp-proxy`},async()=>({tools:(l===`flat`?await(async()=>{let e=await n.getServerDefinitions(),t=await Ci(n,r);return[...vi(e),...t?[wi(e,c)]:[]]})():l===`search`?await(async()=>[Ti(await n.getServerDefinitions(),c),await s.getDefinition(),o.getDefinition()])():l===`group`?xi(await n.getServerDefinitions()):[await a.getDefinition(),o.getDefinition()]).map(e=>{if(e.inputSchema.type!==`object`)throw Error(`Tool ${e.name} must declare an object input schema`);return{...e,inputSchema:{...e.inputSchema,type:`object`}}})}))),p.setRequestHandler(`tools/call`,async e=>{let{name:t,arguments:r}=e.params;return await f(`mcp.server.call_tool`,{"mcp.service":`@agimon-ai/po-mcp-proxy`,"mcp.tool.name":t},async()=>{let e=async(e,t)=>{let n=A(r??{},e.getInputSchema());try{return await e.execute(n)}catch(n){if(n instanceof O.ZodError)return{content:[{type:`text`,text:ze(n,{schemaName:t,schema:e.getInputSchema()})}],isError:!0};throw Error(`Failed to execute ${t}: ${n instanceof Error?n.message:String(n)}`)}};if(t===Y.TOOL_NAME&&l!==`group`)return await e(a,t);if(t===Z.TOOL_NAME&&l!==`group`)return await e(o,t);if(t===ti.TOOL_NAME&&l===`search`)return await e(s,t);let i=l===`group`?yi(t):null;if(i?.metaToolName===Y.TOOL_NAME){let e=J.safeParse(A(r??{},J));if(!e.success)return{content:[{type:`text`,text:ze(e.error,{schemaName:t,schema:J})}],isError:!0};let a=e.data,o=await n.getServerDefinitions(),s=o.find(e=>e.serverName===i.serverName),c=Si(s,a.toolNames);if((c.notFoundItems.length>0||!s)&&(n.clearLiveCache(),await n.collectForCache(),o=await n.getServerDefinitions(),s=o.find(e=>e.serverName===i.serverName),c=Si(s,a.toolNames)),!s)return{content:[{type:`text`,text:`Server "${i.serverName}" not found. Available servers: ${o.map(e=>e.serverName).join(`, `)}`}],isError:!0};if(c.foundTools.length===0)return{content:[{type:`text`,text:`None of the requested tools found on server "${i.serverName}". Requested: ${a.toolNames.join(`, `)}`}],isError:!0};let l={server:i.serverName,tools:c.foundTools,nextSteps:[`Use ${$(i.serverName,Z.TOOL_NAME)} with a plain toolName and toolArgs based on the inputSchema above.`]};return c.notFoundItems.length>0&&(l.notFound=c.notFoundItems),{content:[{type:`text`,text:JSON.stringify(l,null,2)}]}}if(i?.metaToolName===Z.TOOL_NAME){let e=X.safeParse(A(r??{},X));if(!e.success)return{content:[{type:`text`,text:ze(e.error,{schemaName:t,schema:X})}],isError:!0};let n=e.data;return B(n.toolName).serverName?{content:[{type:`text`,text:`Tool "${t}" is already scoped to server "${i.serverName}". Pass the downstream tool name without a server prefix.`}],isError:!0}:await o.execute({toolName:$(i.serverName,n.toolName),toolArgs:n.toolArgs||{}})}if(l===`flat`)return await o.execute({toolName:t,toolArgs:r||{}});throw Error(`Unknown tool: ${t}`)})}),p.setRequestHandler(`resources/list`,async()=>{let e=await n.getServerDefinitions(),t=/* @__PURE__ */ new Map;for(let n of e)for(let e of n.resources)t.has(e.uri)||t.set(e.uri,[]),t.get(e.uri)?.push(n.serverName);let r=[];for(let n of e)for(let e of n.resources){let i=(t.get(e.uri)||[]).length>1;r.push({...e,name:e.name??e.uri,uri:i?`${n.serverName}__${e.uri}`:e.uri})}return{resources:r}}),p.setRequestHandler(`resources/read`,async e=>{let{uri:r}=e.params,{serverName:i,actualToolName:a}=B(r);if(i)return await(await t.ensureConnected(i)).readResource(a);let o=await n.getServersForResource(a);if(o.length===0)throw Error(`Resource not found: ${r}`);if(o.length>1)throw Error(`Resource "${a}" exists on multiple servers: ${o.join(`, `)}. Use the prefixed format (e.g., "${o[0]}__${a}") to specify which server to use.`);return await(await t.ensureConnected(o[0])).readResource(a)}),p.setRequestHandler(`prompts/list`,async()=>{let e=await n.getServerDefinitions(),t=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Map;for(let n of e){r.set(n.serverName,n.prompts);for(let e of n.prompts)t.has(e.name)||t.set(e.name,[]),t.get(e.name).push(n.serverName)}let i=[];for(let n of e){let e=r.get(n.serverName)||[];for(let r of e){let e=(t.get(r.name)||[]).length>1;i.push({name:e?`${n.serverName}__${r.name}`:r.name,description:r.description,arguments:r.arguments})}}return{prompts:i}}),p.setRequestHandler(`prompts/get`,async e=>{let{name:r,arguments:i}=e.params,a=await n.getServerDefinitions(),{serverName:o,actualToolName:s}=B(r);if(o)return await(await t.ensureConnected(o)).getPrompt(s,i);let c=[];for(let e of a)e.prompts.some(e=>e.name===r)&&c.push(e.serverName);if(c.length===0)throw Error(`Prompt not found: ${r}`);if(c.length>1)throw Error(`Prompt "${r}" exists on multiple servers: ${c.join(`, `)}. Use the prefixed format (e.g., "${c[0]}__${r}") to specify which server to use.`);let l=t.getClient(c[0]);return l?await l.getPrompt(r,i):await(await t.ensureConnected(c[0])).getPrompt(r,i)}),p}async function Oi(e){let t=await di(e),n=await Di(t);return Object.assign(n,{dispose:t.dispose}),n}const ki={STDIO:`stdio`,HTTP:`http`,SSE:`sse`};export{$e as $,On as A,Ot as B,Ar as C,nr as D,cr as E,un as F,yt as G,Dt as H,dn as I,xt as J,bt as K,fn as L,yn as M,mn as N,jn as O,pn as P,Xe as Q,cn as R,Nr as S,K as T,kt as U,Tt as V,Ct as W,et as X,pt as Y,tt as Z,zr as _,di as a,ct as at,Vr as b,fi as c,Je as ct,ni as d,j as dt,Qe as et,Z as f,Fr as g,Yr as h,pi as i,dt as it,U as j,An as k,hi as l,We as lt,Y as m,Oi as n,st as nt,Q as o,ut as ot,ti as p,ht as q,Di as r,lt as rt,mi as s,Ze as st,ki as t,Ye as tt,ci as u,qe as ut,Lr as v,Sr as w,Jr as x,qr as y,rn as z};
|